一、配置注解事务管理
在hibernate的sessionFactory配置后面添加如下配置信息
<!-- 配置事务管理器bean,使用HibernateTransactionManager事务管理器 -->
<bean id="transactionManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<!-- 为事务管理器注入sessionFactory" -->
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
<!-- 注解实现事务 -->
<tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true" />
修改hibernate的sessionFactory配置的属性:
<prop key="hibernate.current_session_context_class">org.springframework.orm.hibernate4.SpringSessionContext</prop>
使用spring整合hibernate,并由spring来管理事务时,如果这个属性值设置为thread,那么使用session.getCurrentSession()获取session,调用get、load等方法时,会报异常:org.hibernate.HibernateException: is not valid without active transaction 。可以参考:http://blog.youkuaiyun.com/z69183787/article/details/8768421 。
二、使用注解@Transactional开启spring事务管理
@Transactional默认只有当方法中抛出unchecked的runtimeException时,才会进行回滚,抛出需捕获的Exception异常是不能进行回滚的。如下例子所示:
@Transactional
public void addUser() throws Exception {
User add = new User();
add.setNickName("asd");
add.setPassword("123456");
add.setUrlID("asdadsad");
add.setUserName("12222");
userDao.add(add);
throw new Exception();
}
执行这个方法后,添加用户的操作会被执行,不会进行回滚。
如果将代码改成如下所示:
@Transactional
public void addUser() {
User add = new User();
add.setNickName("asd");
add.setPassword("123456");
add.setUrlID("asdadsad");
add.setUserName("12222");
userDao.add(add);
throw new RuntimeException();
}
就会进行回滚。
值得注意的是如果你在方法中使用try catch捕获了异常,那么事务也不会进行回滚。例如:
@Transactional
public void addUser() {
try {
User add = new User();
add.setNickName("asd");
add.setPassword("123456");
add.setUrlID("asdadsad");
add.setUserName("12222");
userDao.add(add);
throw new RuntimeException();
} catch (Exception e) {
e.printStackTrace();
}
}
事务不会回滚。如果想要回滚,可以在catch中再抛出RuntimeException。
上面描述的是@Transactional默认处理的异常,@Transactional有相应的属性可以设置,例如控制@Transactional处理那些异常等等,具体可以参考spring官方文档。
三、hibernate的SessionFactory的getCurrentSession和openSession
getCurrentSession方法是获取当前上下文的session,该方法必须获取的session进行相应操作时必须在一个事务中进行,否则会报异常org.hibernate.HibernateException: is not valid without active。这个方法获取的session会自动进行关闭。
openSession方法是开启一个新的session,不需要在事务中执行,并且获取的session需要手动进行关闭。
所以在上述配置中,如果方法使用注解@Transactional,就需要使用getCurrentSession。反之,不是使用注解@Transactional,就是不进行事务控制,就是应该使用openSession方法。