views:

615

answers:

4

I have an application that I am currently writing that will use Spring and Hibernate. In my services layer I have injected a DAO that will do some very basic CRUD-ing actions. For grins, I have created a method annotated as follows:

@Transactional(readOnly = false, propogation=Propogation.REQUIRES_NEW)
public void doSomeWork(Dao dao, Entity e){
    //do some searching
    dao.persist(e);
    dao.findAll(Entity.clz);
}

The dao persist method looks like this:

public void persist(Entity e){
     session.saveOrUpdate(e); //This has already been built using a SessionFactory
}

The dao findAll method looks like this

public void findAll(Class clz) {
     session.createCriteria(clz).list();
}

Now, everything seems to run, OK. After I insert (persist) my object, I can see it using the findAll method (along with the new Primary Key ID that it was assigned by the Data Store), however, when the "doSomeWork" method completes, my data does not actually get persisted to the underlying datastore (Oracle 10g).

If, however, I remove the @Transactional annotations and use Hibernate's session.getTransaction().begin() and session.getTransaction().commit() (or rollback), the code works as I would anticipate.

So, my underlying question would then be: Does Hibernate not actually use Spring's transaction management for actual transaction management?

In my bean-config file I am declaring a TransactionManager bean, a SessionFactory bean, and I am also including in the config file.

What could I possibly be missing, aside for a better working-knowledge of Spring and Hibernate?

+1  A: 

what method do you use to obtain the session object from the session factory? Are you using openSession(), or getCurrentSession(), or perhaps something else? This matters because you need to session to be bound to the spring transaction (I doubt if openSession is good for your scenario)

I suggest that you use Spring's hibernateTemplate to invoke saveOrUpdate and persist, instead of using the session object. This way you are guaranteed that it will be bound to the transaction, and, as spring promises, you won't need to change the code if you ever change the transaction management strategy.

Yoni
I actually went down this road and seem to have gotten the same result, however, let me try again.
El Guapo
HibernateTemplate isn't the way to go since spring 2 can inject the sessionfactory automagically. check here: http://swik.net/Spring/Interface21+Team+Blog/So+should+you+still+use+Spring%27s+HibernateTemplate+and%2For+JpaTemplate%3F%3F/bcw59
smeg4brains
+2  A: 

sounds like spring doesnt actually inject the transaction handling code. do you have something like this in your config file, to tell spring where to look for annotated classes?

<beans xmlns:context="http://www.springframework.org/schema/context" ...
    xsi:schemaLocation="http://www.springframework.org/schema/context 
    http://www.springframework.org/schema/context/spring-context-3.0.xsd ..." >

    ...
    <context:annotation-config/>
    <context:component-scan base-package="mypackage.dao.impl"/>

    <bean name="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory"/>
    </bean>

</beans>
smeg4brains
Yes, this is for all intents and purposes exactly what my config looks like. I've also got a SessionFactory bean with my hibernate-config referenced in it... I have a HibernateTemplate with a ref to my SessionFactory bean, as well as, a HibernateTransactionManager with a reference to my SessionFactory bean.
El Guapo
+2  A: 

Don't forget to add <tx:annotation-driven> for @Transactional support

axtavt
+1  A: 

Ok, well, thanks to everyone who responded... it helped me to figure out what I am doing wrong...

In my overzealous "proof-of-concepting" it never really dawned on me what was going on until I realized that my "simple java class with a main method that will be doing all my work" isn't managed by spring, therefore no real transaction management. This will in no way behave as a product application would, being managed by an app-server with controller beans, services, etc.

Then it dawned on me... "services"... I'm going to have a services layer, that's where the transaction support will live. So, right as rain, I created a simple service bean (marked with @Transactional) and it works just as I would hope it would. So, I call methods on my service, which calls methods on my Dao and bam!!! it works.

Thanks again to everyone who helped me to come to this conclusion.

El Guapo