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?
Hibernate deals with database specific transactions, whereas spring provides a general transaction management service. @Transactional is a nice way of configuring transaction management behaviour.
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.
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).
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With