Hibernate and Spring DataSourceTransactionManager
I have been trying to work with Hibernate and Spring DataSourceTransactionManager to handle commit and rollback functionality, but I probably am not getting anything.
Before using Spring DataSourceTransactionManager this was one of my DAO classes
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 sessionFactory gives me
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 am trying to use DataSourceTransactionManager in a declarative way. Following some examples on the internet, I wrote the following:
<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 salvaUtente () method to perform many insertions such as
session.saveOrUpdate(User);
session.saveOrUpdate(UserCredentials);
session.saveOrUpdate(UserOtherDetails);
and do Spring notation and descriptor rollback?
source to share
First you are using the wrong transaction manager. DataSourceTransactionManager
not for hibernate but for plain JDBC. If you are using plain Hibernate use HibernateTransactionManager
. (Let's assume you are using Hibernate 4 here!).
<bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
Now I propose to use @Transactional
instead of the block <tx:advice />
and <aop:config />
. Makes your configuration easier. Just remove the 2 blocks mentioned and replace them with <tx:annotation-driven />
.
<tx:annotation-driven />
Now your code is wrong when you start transactions yourself. Annotate your method with @Transactional
(after adding above) and remove the 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 method does getHibenateSession
, but make sure you don't use openSession
in SessionFactory
to get the session. Use instead getCurrentSession
.
protected Session getHibernateSession() {
return sessionFactory.getCurrentSession();
}
Your current class BaseDAO
is wrong. Uninstall buildSessionFactory
and uninstall static final
. Let Spring configure and enter SessionFactory
.
public abstract class BaseDAO {
@Autowired
private SessionFactory sessionFactory;
protected Session getHibernateSession() {
return sessionFactory.getCurrentSession();
}
}
In your config add the config for LocalSessionFactoryBean
.
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
... Other Hibernate Properties
</bean>
This is basically all it takes. This is also detailed in the Spring reference manual . I highly recommend reading.
source to share
I would suggest
@Transaction(rollbackFor = {if you need to rollback on certain checked exception})
salvaUtente()
The transaction is executed only for an unchecked exception, unless otherwise noted.
if there is any exception at any point in the salvaUtente in the transaction it will be rolled back, otherwise the transaction will be committed after the method exists
source to share