As I understand it, Hibernate ensures that two copies of the same data loaded in the same session resolve to the same object instance.
So the code below should work:
testbed:
zoneManagerDoaCode:protected void setUp () throws Exception { : ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext (xmlLocs) ; zoneManager = (ZoneManager) ac.getBean ("zoneManager") ; hibernateTemplate = (HibernateTemplate) ac.getBean ("hibernateTemplate") ; } protected void tearDown () { } public void testEquals () throws Exception { int c = zoneManager.count () ; assertEquals (c, 0) ; Zone zone1 = TestUtils.makeZone (1) ; zoneManager.add (zone1) ; Zone zoneOut1 = zoneManager.get (1) ; assertSame (zone1, zoneOut1) ; // Destroy 1st & 2nd level cache hibernateTemplate.flush () ; hibernateTemplate.clear () ; zoneOut1 = zoneManager.get (1) ; assertNotSame (zone1, zoneOut1) ; }
contextCode:@Transactional public class ZoneManagerDaoHibernate implements ZoneManagerDao { private HibernateTemplate hibernateTemplate ; public ZoneManagerDaoHibernate() { // } public void setHibernateTemplate (HibernateTemplate hibernateTemplate) { this.hibernateTemplate = hibernateTemplate ; } public Zone get (int id) { Object values[] = new Object[1] ; values[0] = new Integer (id) ; @SuppressWarnings("unchecked") List<Zone> l = hibernateTemplate.find ("from Zone z where z.id=?", values) ; if (l.size () == 0) return null ; Zone z = l.get (0) ; z.getClips ().size () ; return z ; } public int count () { @SuppressWarnings("unchecked") List<Zone> l = hibernateTemplate.find ("from Zone z") ; return l.size() ; } public int add (Zone z) { Integer i = (Integer) hibernateTemplate.save (z) ; return Integer.valueOf (i) ; } }
This is running under a JUnit test which is failing on "assertSame (zone1, zoneOut1) ;" that is the object returned from the get is not the same object as was placed in the zoneManager.Code:<bean id="hypersonicDatasource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="org.hsqldb.jdbcDriver"/> <property name="url" value="jdbc:hsqldb:mem:dbname"/> <property name="username" value="sa"/> <property name="password" value=""/> </bean> <bean id="dataSource" class="com.xxx.sitemanager.testdb.TestDataSourceFactory"> <property name="datasource" ref="hypersonicDatasource"/> </bean> <tx:annotation-driven transaction-manager="transactionManager"/> <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"> <property name="dataSource" ref="dataSource" /> <property name="mappingResources"> <list> <value>my hbm.xml</value> <value>my hbm.xml</value> </list> </property> <property name="hibernateProperties"> <props> <prop key="hibernate.dialect">org.hibernate.dialect.HSQLDialect</prop> <prop key="hibernate.show_sql">true</prop> <prop key="hibernate.format_sql">true</prop> <prop key="hibernate.hbm2ddl.auto">create-drop</prop> </props> </property> </bean> <bean id="hibernateTemplate" class="org.springframework.orm.hibernate3.HibernateTemplate"> <property name="sessionFactory" ref="sessionFactory"/> </bean> <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"> <property name="sessionFactory" ref="sessionFactory"/> </bean> <bean id="zoneManagerDaoHibernate" class="com.xxx.SiteManager.adaptor.isa.zone.ZoneManagerDaoHibernate"> <property name="hibernateTemplate" ref="hibernateTemplate"/> </bean> <bean id="zoneManager" class="com.xxx.SiteManager.adaptor.isa.zone.ZoneManager"> <property name="zoneManagerDao" ref="zoneManagerDaoHibernate"/> </bean>
If I change setup() to:
and the tearDown() to:Code:ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext (xmlLocs) ; zoneManager = (ZoneManager) ac.getBean ("zoneManager") ; hibernateTemplate = (HibernateTemplate) ac.getBean ("hibernateTemplate") ; session = SessionFactoryUtils.getSession (hibernateTemplate .getSessionFactory (), true) ; TransactionSynchronizationManager.bindResource (hibernateTemplate.getSessionFactory (), new SessionHolder ( session)) ; }
Then it all works.Code:protected void tearDown () { TransactionSynchronizationManager.unbindResource (hibernateTemplate .getSessionFactory ()) ; SessionFactoryUtils.releaseSession (session, hibernateTemplate.getSessionFactory ()) ; }
My question is:
1. The (at)Transactional annotations in the zoneManager are picked up so I'm not getting LazyInitialisation when hydrating other objects, so why is it that I need this extra code to explicitly bind a transaction manager when my beans are already using a transaction manager with the hibernate sessionFactory?
2. All the examples I have seen do not use the TransactionSynchronizationManager so is there a way of doing this in the xml file? Is this the accepted way to run these tests?
I have been struggling with this and LazyIEs for over a week, so any help or advice will be greatly appreciated.


Reply With Quote
