Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 462
MDP Avatar asked Nov 12 '14 14:11

MDP


People also ask

What is the difference between Spring transaction and hibernate transaction?

Hibernate deals with database specific transactions, whereas spring provides a general transaction management service. @Transactional is a nice way of configuring transaction management behaviour.

What is use of @transactional annotation in Spring?

The @Transactional annotation makes use of the attributes rollbackFor or rollbackForClassName to rollback the transactions, and the attributes noRollbackFor or noRollbackForClassName to avoid rollback on listed exceptions. The default rollback behavior in the declarative approach will rollback on runtime exceptions.

What is @transactional in hibernate?

A transaction simply represents a unit of work. In such case, if one step fails, the whole transaction fails (which is termed as atomicity). A transaction can be described by ACID properties (Atomicity, Consistency, Isolation and Durability).


1 Answers

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.

like image 71
M. Deinum Avatar answered Oct 12 '22 10:10

M. Deinum