MDP
MDP

Reputation: 4267

Hibernate and Spring DataSourceTransactionManager

I'm trying to work with Hibernate and Spring DataSourceTransactionManager to handle commit and rollback functions, but probably I dind't get something.

Before using Spring DataSourceTransactionManager, this was one of my DAO class

  package com.springgestioneerrori.DAO;

  public class UtenteDAO extends DAOBase{   

       public void salvaUtente(Utente utenteIn) throws DAOException{ 

            Session session = getHibernateSession(); //from this method  I get Hibernate SessionFactory
              try{   
                  session.beginTransaction();             
                  session.saveOrUpdate(Object); 
                  session.getTransaction().commit();    
                  }
              catch(Exception e){
                  session.getTransaction().rollback()
              }
        }
}

This is the class that give me the sessionFactory

 private static final SessionFactory sessionFactory = buildSessionFactory();

            private static SessionFactory buildSessionFactory() {
                try {
                    // Create the SessionFactory from hibernate.cfg.xml
                    return new AnnotationConfiguration().configure().buildSessionFactory();  
                }
                catch (Throwable ex) {
                              System.err.println("Initial SessionFactory creation failed." + ex);
                    throw new ExceptionInInitializerError(ex);
                }
            }

            public static SessionFactory getSessionFactory() {
                return sessionFactory;
            }

            public static void shutdown() {             
                getSessionFactory().close();
            }

public Session getHibernateSession (){
    Session session = HibernateUtil.getSessionFactory().openSession();
    return session;
}   

Now i'm trying to use DataSourceTransactionManager in a declarative way. Following some examples on the internet I wrote this:

 <tx:annotation-driven proxy-target-class="true" transaction-manager="transactionManager" />        

<tx:advice id="txAdvice" transaction-manager="transactionManager">
    <tx:attributes>
        <tx:method name="salvaUtente"/>
    </tx:attributes>
</tx:advice>

<aop:config>
    <aop:pointcut id="userDaoTxPointcut" expression="execution(* com.springgestioneerrori.DAO.UtenteDAO.salvaUtente(..))" />
    <aop:advisor advice-ref="txAdvice" pointcut-ref="userDaoTxPointcut" />
</aop:config>       

Now, what should I write inside the method salvaUtente() to perform many inserts, for example like these

  session.saveOrUpdate(User); 
  session.saveOrUpdate(UserCredentials); 
  session.saveOrUpdate(UserOtherDetails); 

and making Spring handle commint and rollback?

Upvotes: 5

Views: 4874

Answers (3)

Mahesh
Mahesh

Reputation: 441

HibernateTransactionManager can also manage the transactions on the DataSource. We need to inject the DataSource in the HibernateTransactionManager and it should work for both, Hibernate and plain old SQL.

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

Hope this works for you.

(I know this is pretty late, but may help someone landing to this post)

Upvotes: 0

M. Deinum
M. Deinum

Reputation: 124909

First you are using the wrong transaction manager. The DataSourceTransactionManager isn't for Hibernate but for plain JDBC. If you are using plain Hibernate use the HibernateTransactionManager. (Assuming that you are using Hibernate 4 here!).

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

Now I would also suggest to use @Transactional instead of a <tx:advice /> and <aop:config /> block. Makes your configuration easier. Simply remove the 2 mentioned blocks and replace with <tx:annotation-driven />.

<tx:annotation-driven />

Now your code is wrong as you are starting transactions yourself. Annotate your method with @Transactional (after adding the thing above) and remove your transaction handling code.

@Transactional
public void salvaUtente(Utente utenteIn) throws DAOException{ 
    Session session = getHibernateSession(); //from this method  I get Hibernate SessionFactory
    session.saveOrUpdate(Object); 
}

Now I don't know what your getHibenateSession method does but make sure you don't use openSession on the SessionFactory to obtain a session. Use getCurrentSession instead.

protected Session getHibernateSession() {
    return sessionFactory.getCurrentSession();
}

Your current BaseDAO class is flawed. Delete your buildSessionFactory and remove the static final. Let Spring configure and inject the SessionFactory.

public abstract class BaseDAO {

    @Autowired
    private SessionFactory sessionFactory;

    protected Session getHibernateSession() {
        return sessionFactory.getCurrentSession();
    }
}

In your configuration add the configuration for the LocalSessionFactoryBean.

<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
    <property name="dataSource" ref="dataSource" />
    ... Other Hibernate Properties
</bean>

That is basically all that is needed. This is also all explained in detail in the Spring Reference guide. I strongly suggest a read.

Upvotes: 5

Neelam Mehta
Neelam Mehta

Reputation: 184

I would suggest

@Transaction(rollbackFor = {if you need to rollback on certain checked exception})
salvaUtente()

The transaction is only roll backed for unchecked exception until mentioned otherwise.

if there is an exception at any point salvaUtente in the transaction will be roll backed else the transaction will be committed once the method is existed

Upvotes: 0

Related Questions