PDA

View Full Version : Object identity with HibernateTemplate



Sebastian
Aug 25th, 2004, 04:59 AM
Hi!
I am using Spring with Hibernate, and i am confused by the following (taken from a junit test):


Subject subject1a = (Subject) getHibernateTemplate().find("FROM Subject s WHERE s.title='Subject 1'").get(0);
Subject subject1b = (Subject) getHibernateTemplate().find("FROM Subject s WHERE s.title='Subject 1'").get(0);

// the following fails!
assertTrues(subject1a==subject1b);


I read the Hibernate manual on Identity/Equals, and i thought that the two find's should return exactly the same object (in terms of Java-VM identity). Am i wrong about that?

I tried the same with a "plain" Hibernate session:

Subject subject1a = (Subject) hibernateSession.find("FROM Subject s WHERE s.title='Subject 1'").get(0);
Subject subject1b = (Subject) hibernateSession.find("FROM Subject s WHERE s.title='Subject 1'").get(0);

// the following is true!
assertTrue(subject1a==subject1b);


And this works. I thought HibernateTemplate would store the HibernateSession in a thread bound variable and reuse it on the next call. But apparently in the first code snippet a new session is opened for every find-call.

Did i miss something important?

I will post more information about my setup below.

Thanks for your help!
Sebastian

Sebastian
Aug 25th, 2004, 05:04 AM
BTW: I also tried this identity comparison in a controller, with my (otherwise working) Managers and DAOs. The comparison failed there, too...

In the JUnit test i setUp the following:

sessionFactory = new LocalSessionFactoryBean();
sessionFactory.setConfigLocation(new ClassPathResource("hibernate.cfg.xml"));
sessionFactory.afterPropertiesSet();

hibTempl = new HibernateTemplate((SessionFactory) sessionFactory.getObject());

(the method getHibernateTemplate() in my JUnit test simply returns hibTempl)

Rod Johnson
Aug 25th, 2004, 07:35 AM
Spring will only do the ThreadLocal binding in the context of a single transaction. You need to create a transaction in your tests, using Spring's declarative tx management or programmatically with the HibernateTransactionManager. I typically use an abstract integration test superclass that creates a transaction in setUp() and rolls it back in tearDown().

Colin Sampaleanu
Aug 25th, 2004, 04:19 PM
This is why I personally also always set up my HibernateTemplates with the allowCreate flag set to off (session must already exist, presumably set up alongside the transaction by HibernateTransactionManager or another transaction manager+HibernateInterceptor).

With the flag set to the default true, it's too easy to run code out of a transaction, and accidentally create a session when you don't realize it...

Regards,

Sebastian
Aug 26th, 2004, 02:11 AM
Hi Rod, Colin!

Thanks for your replies! This solved my problem... :-)

Sebastian