Frage

Ich versuche, einer Sammlung in einem anderen Pojo ein Pojo hinzuzufügen. Ich bin sicher, ich mache irgendwo in der Schlange einen wirklich dummen Fehler, aber ich kann nicht herausfinden, wie ich ihn lösen kann.

Ich habe ein Pojo, das eine Liste von Spalten enthält:

public class LookupTable {
  private long id;
  // More properties go here...
  private List<Column> columns;

  public void addColumn(Column column) {
    this.columns.add(column);
  }

  // More methods go here...
}

In meiner Hibernate -Konfiguration habe ich:

<class name="LookupTable" table="ARR_LOOKUP_TABLE">
  <id name="id" column="ID">
    <generator class="native"/>
  </id>
  <!-- Some properties here -->
  <bag name="columns" cascade="all,delete-orphan" access="field">
    <key column="LOOKUP_TABLE" not-null="true"/>
    <one-to-many class="Column"/>
  </bag>
</class>

<class name="Column" table="ARR_LOOKUP_COLUMN">
  <id name="id" column="ID">
    <generator class="native"/>
  </id>
  <!-- Some properties here -->
</class>

In meiner Spring -Konfigurationsdatei habe ich:

<tx:advice id="txAdvice" transaction-manager="txManager">
  <tx:attributes>
    <tx:method name="*" propagation="REQUIRED"/>
  </tx:attributes>
</tx:advice>
<aop:config>
  <aop:pointcut id="managers" expression="execution(public * com.foo.*Manager.*(..))"/>
  <aop:advisor advice-ref="txAdvice" pointcut-ref="managers"/>
</aop:config>

Und schließlich der Code, in dem alles in meiner Managerklasse fehlschlägt (com.foo.lookuptablemanager):

public void addColumnToTable(Column column, long tableId) {
  LookupTable lookupTable = this.lookupTableDao.findById(tableId);
  lookupTable.addColumn(column);
  this.lookupTableDao.saveOrUpdate(lookupTable);
}

Die variable Lookuptabledao bezieht sich hier auf eine einfache DAO -Klasse, die hibernatedaosupport erweitert.

Der Fehler, den ich bekomme, ist:

org.hibernate.HibernateException: Illegal attempt to associate a collection with two open sessions
  at org.hibernate.collection.AbstractPersistentCollection.setCurrentSession(AbstractPersistentCollection.java:410)
  at org.hibernate.event.def.OnUpdateVisitor.processCollection(OnUpdateVisitor.java:43)
  at org.hibernate.event.def.AbstractVisitor.processValue(AbstractVisitor.java:101)
  at org.hibernate.event.def.AbstractVisitor.processValue(AbstractVisitor.java:61)
  at org.hibernate.event.def.AbstractVisitor.processEntityPropertyValues(AbstractVisitor.java:55)
  at org.hibernate.event.def.AbstractVisitor.process(AbstractVisitor.java:123)
  at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.performUpdate(DefaultSaveOrUpdateEventListener.java:293)
  at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.entityIsDetached(DefaultSaveOrUpdateEventListener.java:223)
  at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.performSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:89)
  at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:70)
  at org.hibernate.impl.SessionImpl.fireSaveOrUpdate(SessionImpl.java:507)
  at org.hibernate.impl.SessionImpl.saveOrUpdate(SessionImpl.java:499)
  at org.hibernate.impl.SessionImpl.saveOrUpdate(SessionImpl.java:495)
  at com.foo.AbstractDao.saveOrUpdate(AbstractDao.java:29)
  at com.foo.LookupTableManager.addColumnToTable(LookupTableManager.java:338)
... etc ...

Ok, ich verstehe die grundlegende Nachricht, die ich bekomme. Aber ich verstehe nicht, wo ich die zweite Sitzung bekomme .... Kann mir jemand dabei helfen?

Ich verwende Hibernate 3.2.6.ga, Frühling 2.5.5 und Tomcat 6.0

War es hilfreich?

Lösung

Es stellte sich heraus, dass ich überhaupt keine Transaktion hatte. Ich habe in einer meiner anderen Konfigurationsdateien fast dieselbe Transaktionskonfiguration verwendet.

Der Pointcut dort wurde auch "Manager" genannt, so dass mein Berater hier auf den Pointcut in der anderen Datei verwies.

Das Umbenennen des Pointcut löste mein Problem.

Andere Tipps

Ich vermute, dass die lookupTableDao.findById Anruf erhält Ihr Objekt in einer Sitzung, aber die lookupTableDao.saveOrUpdate ist ein anderer - wie bekommst du das? Session Objekt über Frühling?

Wo ist der, die, das Column Objekt kommt von - ist das schon auf der dB oder neu?

Das Problem war die offene Sitzung in der Ansichtsfilter Mapping. Es wurde eine Sitzung über GetSession und andere auf Save erstellt.

Sie können nur SingleSession als falsches Standard ändern, es ist wahr

Anscheinend wird die Verwendung von Merge das Problem wahrscheinlich beheben

myInstance = (myInstanceClass) Session.merge(myInstance);

Ich hatte das gleiche Problem mit meinem folgenden Code: Ich wollte einen bestimmten Entitätsgeschäft aktualisieren. Ich habe es aus dieser Methode abgerufen:

@Override
public Store getStoreByStoreId(final long storeId) {
    getHibernateTemplate().execute(new HibernateCallback<Store>() {
        @Override
        public StoredoInHibernate(Session session) throws HibernateException, SQLException {
            return (Store) session.createCriteria(Store.class)
                    .add(Restrictions.eq(Store.PROP_ID, storeId))
                    .uniqueResult();
        }
    });
}

Dann habe ich den Laden in der folgenden Methode aktualisiert:

@Override
public void updateStoreByStoreId(final long storeId) {
    getHibernateTemplate().execute(new HibernateCallback<Void>() {
        @Override
        public Void doInHibernate(Session session) throws HibernateException, SQLException {
            Store toBeUpdated =  getStoreByStoreId(storeId);

            if (toBeUpdated != null){
                // ..change values for certain fields
                session.update(toBeUpdated);
            }
            return null;
        }
    });
} 

Es stellte sich heraus, dass ich den Fehler "Illegaler ..." bekam, weil die erste Sitzung aus der Get -Methode nicht schließt und ich versuchte, mit der anderen Sitzung im Geschäft zu aktualisieren. Die Lösung für mich bestand darin, den Aufruf zum Abrufen des Store zu verschieben, das in der Update -Methode aktualisiert werden soll.

@Override
public void updateStoreByStoreId(final long storeId) {
    getHibernateTemplate().execute(new HibernateCallback<Void>() {
        @Override
        public Void doInHibernate(Session session) throws HibernateException, SQLException {
            Store toBeUpdated =  (Store) session.createCriteria(Store.class)
                    .add(Restrictions.eq(Store.PROP_ID, storeId))
                    .uniqueResult();

            if (toBeUpdated != null){
                // ..change values for certain fields
                session.update(toBeUpdated );
            }
            return null;
        }
    });
} 

Wenn Sie nur eine Transaktion über einen Teil Ihres Codes wünschen, können Sie so etwas verwenden:

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;

und in der Klasse:

@Autowired private SessionFactory sessionFactory;

Später um den Code um den Code, der Dinge in derselben Transaktion ausführen sollte:

Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();

Stuff stuff = getStuff();
manipulate(stuff);
send(stuff);
save(stuff);

tx.commit();

Ich benutze dies in einer Schleife in einigen langjährigen Batch-Jobs.

Ich habe Windows Server IIS verwendet und habe gerade den Apppool -verwalteten Pipeline -Modus von integriert zu klassisch gelöst mein Problem geändert.

Vielen Dank

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top