0

First, I'll describe a little bit the conceptional project, that I'm trying to get working:

There is a database with two schemas, PROD and ARCHIVE and some entity tables in it: TestA, TestB, TestC, TestL. The structure of the tables in both schemas is exactly the same.

TestA has - a many-to-one relation to TestL (lookup table), - a one-to-many relation to TestB, TestB has a one-to-many relation to TestC.

hibernate-prod.cfg.xml

<?xml version='1.0' encoding='utf-8'?> <!DOCTYPE hibernate-configuration PUBLIC
    "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">

<hibernate-configuration>

    <session-factory>
        <property name="connection.datasource">arcTestDs</property>

        <property name="dialect">org.hibernate.dialect.DB2Dialect</property>

        <property name="default_schema">PROD</property>

        <property name="current_session_context_class">jta</property>
        <property name="hibernate.transaction.manager_lookup_class">org.hibernate.transaction.BTMTransactionManagerLookup</property>
        <property name="hibernate.transaction.factory_class">com.imd.tracking.arc_test.dao.LocalJtaTransactionFactory</property>
        <property name="hibernate.default_schema">PROD</property>
        <property name="hibernate.hbm2ddl.auto">validate</property>
        <property name="cache.provider_class">org.hibernate.cache.NoCacheProvider</property>
        <property name="hibernate.c3p0.timeout">1000</property>
        <property name="show_sql">true</property>

        <mapping resource="com/imd/tracking/arc_test/domain/TestADTO.hbm.xml" />
        <mapping resource="com/imd/tracking/arc_test/domain/TestBDTO.hbm.xml" />
        <mapping resource="com/imd/tracking/arc_test/domain/TestCDTO.hbm.xml" />
        <mapping resource="com/imd/tracking/arc_test/domain/TestLDTO.hbm.xml" />

    </session-factory>

</hibernate-configuration>

hibernate-arc.cfg.xml

<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
    "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">

<hibernate-configuration>

    <session-factory>
        <property name="connection.datasource">arcTestDs</property>

        <property name="dialect">org.hibernate.dialect.DB2Dialect</property>

        <property name="default_schema">ARCHIVE</property>

        <property name="current_session_context_class">jta</property>
        <property name="hibernate.transaction.manager_lookup_class">org.hibernate.transaction.BTMTransactionManagerLookup</property>
        <property name="hibernate.transaction.factory_class">com.imd.tracking.arc_test.dao.LocalJtaTransactionFactory</property>
        <property name="hibernate.default_schema">ARCHIVE</property>
        <property name="hibernate.hbm2ddl.auto">validate</property>
        <property name="cache.provider_class">org.hibernate.cache.NoCacheProvider</property>
        <property name="hibernate.c3p0.timeout">1000</property>
        <property name="show_sql">true</property>

        <mapping resource="com/imd/tracking/arc_test/domain/TestADTO.hbm.xml" />
        <mapping resource="com/imd/tracking/arc_test/domain/TestBDTO.hbm.xml" />
        <mapping resource="com/imd/tracking/arc_test/domain/TestCDTO.hbm.xml" />
        <mapping resource="com/imd/tracking/arc_test/domain/TestLDTO.hbm.xml" />

    </session-factory>

</hibernate-configuration>

TestADTO.hbm.xml

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>

    <class name="com.imd.tracking.arc_test.domain.TestADTO" table="TESTA">
        <id column="IDX" name="idx" type="integer">
            <generator class="identity" />
        </id>
        <property column="C1" generated="never" lazy="false" name="c1"
            type="string" />
        <property column="I1" generated="never" lazy="false" name="i1"
            type="integer" />
        <many-to-one class="com.imd.tracking.arc_test.domain.TestLDTO"
            column="TEXT" fetch="join" name="text" />
        <set cascade="all-delete-orphan" inverse="true" lazy="false" name="bs"
            sort="unsorted">
            <key column="A_IDX" not-null="true" />
            <one-to-many class="com.imd.tracking.arc_test.domain.TestBDTO" />
        </set>
    </class>
</hibernate-mapping>

TestBDTO.hbm.xml

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">

<hibernate-mapping>

        <class name="com.imd.tracking.arc_test.domain.TestBDTO" table="TESTB">
        <id name="idx" type="integer" column="IDX"> 
            <generator class="identity"/>
        </id>

        <many-to-one fetch="join" name="a" column="A_IDX" class="com.imd.tracking.arc_test.domain.TestADTO" />
        <property name="i1" type="integer" column="I1"/>
        <property name="i2" type="integer" column="I2"/>

        <set name="cs"  lazy="false" inverse="true" cascade="all-delete-orphan">
            <key column="B_IDX" not-null="true"/>
            <one-to-many class="com.imd.tracking.arc_test.domain.TestCDTO"/>
        </set>
        </class>
</hibernate-mapping>

TestCDTO.hbm.xml

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "C://DTDs//hibernate-mapping-3.0.dtd">

<hibernate-mapping>

        <class name="com.imd.tracking.arc_test.domain.TestCDTO" table="TESTC">
        <id name="idx" type="integer" column="IDX"> 
            <generator class="identity"/>
        </id>

        <many-to-one fetch="join" name="b" column="B_IDX" class="com.imd.tracking.arc_test.domain.TestBDTO" />

        <property name="i1" type="integer" column="I1"/>
        <property name="i2" type="integer" column="I2"/>
        </class>
</hibernate-mapping>

TestLDTO.hbm.xml

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "C://DTDs//hibernate-mapping-3.0.dtd">

<hibernate-mapping>

        <class name="com.imd.tracking.arc_test.domain.TestLDTO" table="TESTL">
        <id name="idx" type="integer" column="IDX"> 
            <generator class="identity"/>
        </id>

        <property name="text" type="string" >
            <column name="TEXT" sql-type="char(20)"/>
        </property>
        </class>
</hibernate-mapping>

Now, I got two session-factories using a datasource and a jta-transaction-manager.

in my initialization code, I configure the two session-factories with the following code:

sfProd = (SessionFactory)new Configuration()
    .configure("/hibernate-prod.cfg.xml")
    .setProperty(Environment.DEFAULT_SCHEMA, "PROD")
    .buildSessionFactory();

sfArc = (SessionFactory)new Configuration()
    .configure("/hibernate-arc.cfg.xml")
    .setProperty(Environment.DEFAULT_SCHEMA, "ARCHIVE")
    .buildSessionFactory();

Now, i want to select a TestADTO by code like this:

    @Transactional
    public void moveTest(int moveId)
    {
        Session s_prod = sfProd.getCurrentSession();

        @SuppressWarnings("unchecked")
        List<TestADTO> res = (s_prod.createCriteria(TestADTO.class)
        .add(Restrictions.idEq(moveId)).list());  

        TestADTO testA = res.get(0);
        // s_prod.evict(testA); // are those lines needed?
        // s_prod.evict(testA.getText());

        Session s_arc = sfArc.getCurrentSession();

        s_arc.save(testA.getText());
        s_arc.save(testA);

        // later: s_prod.delete(testA);
    }

1) if I just run the above code, I get the error

04.02.2016 12:58:03 com.imd.tracking.arc_test.App [main] DEBUG          org.hibernate.HibernateException: Illegal attempt to associate a collection with two open sessions
    at org.hibernate.collection.AbstractPersistentCollection.setCurrentSession(AbstractPersistentCollection.java:432)
    at org.hibernate.event.def.WrapVisitor.processCollection(WrapVisitor.java:67)
    at org.hibernate.event.def.AbstractVisitor.processValue(AbstractVisitor.java:124)
    at org.hibernate.event.def.WrapVisitor.processValue(WrapVisitor.java:121)
    at org.hibernate.event.def.AbstractVisitor.processEntityPropertyValues(AbstractVisitor.java:78)
    at org.hibernate.event.def.AbstractSaveEventListener.visitCollectionsBeforeSave(AbstractSaveEventListener.java:391)
    at org.hibernate.event.def.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:296)
    at org.hibernate.event.def.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:204)
    at org.hibernate.event.def.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:130)
    at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.saveWithGeneratedOrRequestedId(DefaultSaveOrUpdateEventListener.java:210)
    at org.hibernate.event.def.DefaultSaveEventListener.saveWithGeneratedOrRequestedId(DefaultSaveEventListener.java:56)
    at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.entityIsTransient(DefaultSaveOrUpdateEventListener.java:195)
    at org.hibernate.event.def.DefaultSaveEventListener.performSaveOrUpdate(DefaultSaveEventListener.java:50)
    at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:93)
    at org.hibernate.impl.SessionImpl.fireSave(SessionImpl.java:705)
    at org.hibernate.impl.SessionImpl.save(SessionImpl.java:693)
    at org.hibernate.impl.SessionImpl.save(SessionImpl.java:689)
    at com.imd.tracking.arc_test.dao.Dao.moveTest(Dao.java:161)
    at com.imd.tracking.arc_test.dao.Dao$$FastClassByCGLIB$$464493ab.invoke(<generated>)
    at net.sf.cglib.proxy.MethodProxy.invoke(MethodProxy.java:191)
    at org.springframework.aop.framework.Cglib2AopProxy$CglibMethodInvocation.invokeJoinpoint(Cglib2AopProxy.java:688)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150)
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:110)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
    at org.springframework.aop.framework.Cglib2AopProxy$DynamicAdvisedInterceptor.intercept(Cglib2AopProxy.java:621)
    at com.imd.tracking.arc_test.dao.Dao$$EnhancerByCGLIB$$dacf9fd6.moveTest(<generated>)
    at com.imd.tracking.arc_test.App.go(App.java:106)
    at com.imd.tracking.arc_test.App.main(App.java:120)

The exception is thrown when calling s_arc.save(testA.getText());

2) if I detach the dto's with s_prod.evict(testA); and s_prod.evict(testA.getText());, I get the error:

org.hibernate.HibernateException: Don't change the reference to a collection with cascade="all-delete-orphan": com.imd.tracking.arc_test.domain.TestADTO.bs
    at org.hibernate.engine.Collections.prepareCollectionForUpdate(Collections.java:248)
    at org.hibernate.engine.Collections.processReachableCollection(Collections.java:207)
    at org.hibernate.event.def.FlushVisitor.processCollection(FlushVisitor.java:60)
    at org.hibernate.event.def.AbstractVisitor.processValue(AbstractVisitor.java:124)
    at org.hibernate.event.def.AbstractVisitor.processValue(AbstractVisitor.java:84)
    at org.hibernate.event.def.AbstractVisitor.processEntityPropertyValues(AbstractVisitor.java:78)
    at org.hibernate.event.def.DefaultFlushEntityEventListener.onFlushEntity(DefaultFlushEntityEventListener.java:165)
    at org.hibernate.event.def.AbstractFlushingEventListener.flushEntities(AbstractFlushingEventListener.java:219)
    at org.hibernate.event.def.AbstractFlushingEventListener.flushEverythingToExecutions(AbstractFlushingEventListener.java:99)
    at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:50)
    at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1206)
    at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:375)
    at org.hibernate.transaction.CacheSynchronization.beforeCompletion(CacheSynchronization.java:88)
    at bitronix.tm.BitronixTransaction.fireBeforeCompletionEvent(BitronixTransaction.java:478)
    at bitronix.tm.BitronixTransaction.commit(BitronixTransaction.java:193)
    at bitronix.tm.BitronixTransactionManager.commit(BitronixTransactionManager.java:120)
    at org.springframework.transaction.jta.JtaTransactionManager.doCommit(JtaTransactionManager.java:1009)
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:754)
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:723)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:374)
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:120)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
    at org.springframework.aop.framework.Cglib2AopProxy$DynamicAdvisedInterceptor.intercept(Cglib2AopProxy.java:621)
    at com.imd.tracking.arc_test.dao.Dao$$EnhancerByCGLIB$$359759b9.moveTest(<generated>)
    at com.imd.tracking.arc_test.App.go(App.java:106)
    at com.imd.tracking.arc_test.App.main(App.java:120)

when leaving the method moveTest(int moveId), I think, the exception is thrown when the transaction is commited.

My goal for the real project is to call a function like moveTest(int moveId) for a list of ids. This should be done in batch process which is planned to be run once a day.

QUESTION: How can I move dtos from one session to another?

P.S.: the real DTOs are having much more relations, so I want to avoid deep copies, if possible.

Markus
  • 357
  • 2
  • 13

1 Answers1

-1

I believe that the problem is that your entity is engaged with another session. Anyway you can try to use merge() method instead save()

Maybe this link would help to you Hibernate Save Object to Multiple Sessions

Community
  • 1
  • 1
Dante
  • 279
  • 1
  • 19