spring没有直接管理事务,而是将管理事务的责任委托给JTA或相应的持久性机制所提供的某个特定平台的事务实现。spring容器负责事物的操作,spring容器充当切面,事务的方法称为增强处理,生成的代理对象的方法就是目标方法+增强也就是crud+事务程序员只用做crud的操作,也就是目标方法和声明哪些方法应该在事务中运行。
Spring提供了许多内置事务管理器实现:
Spring不仅提供这些事务管理器,还提供对如JMS事务管理的管理器等,Spring提供一致的事务抽象如图所示
spring与hibernate
说明:
spring在调用具体的事务管理器之前做了一些准备工作,提前设置事务的读写策略,而这些事务策略是公共的东西,是写在spring的配置文件中的,这些内容的处理需要放在抽象类中去做
引入properties配置文件
classpath:jdbc.properties
classpath:hibernate.cfg.xml
注入dao和service层
作用:
1、告诉spring容器事务管理器2、告诉spring容器什么样的方法使用什么样的事务
dao实现类
* 实现方法一:继承HibernateDaoSupport
* @author qjc
*/
public class PersonDaoImpl extends HibernateDaoSupport implements PersonDao{
@Override
public void savePerson(Person person) {
this.getHibernateTemplate().save(person);
}
}
...
注意:
1、如果一个DAO类继承了HibernateDaoSupport,只需要在spring配置文件中注入SessionFactory就可以了。
2、如果一个DAO类没有继承HibernateDaoSupport,需要有一个SessionFactory的属性,并且在配置文件中进行注入。
1、在配置文件中应用spring的自动扫描机制
注意:如果在类级别上被注解为只读事务,但是这个类中的方法中@Transaction注解的事务设置将优先于类级别注解的事务设置。
required: 业务方法需要在一个事务中运行。如果方法运行时,已经处在一个事务中,那么加入到该事务,否则为自己创建一个新事务(默认)
not-supported:spring容器不开启事务,如果方法在一个事务中被调用,该事务会被挂起,该方法结束后,事务恢复
requiresnew:不管是否存在事务,业务方法总会创建一个新事务。
mandatorky: 业务方法只能在一个已经存在的事务中执行,如果业务方法在没有事务下调用,容器抛出例外。
此外还有supports、never、nested等属性,但是通常使用默认
propagation="required" 此配置可以解决事务嵌套问题,何为事务嵌套?
比如:
在工作流框架和操作service层的某个方法中都存在事务,service层也有自己的事务,当service执行的时候,就会出现事务嵌套,即方法本身有事务,方法中的方法还有事务,这就是事务嵌套。而spring通过事务传播属性propagation="required"解决了这一问题。
在s2sh整合以后,spring管理事务,由于使用的是spring的声明式事务处理方式,所以在调用this.getHibernateTemplate()这个方法执行完之后,session立即关闭,如果当前执行的方法有事务,当事务环境的方法被调用完毕后session关闭。所以当值在页面输出时会产生异常。
处理方式为:OpenSessionInview模式(web.xml中配置)
hibernateFilter
org.springframework.orm.hibernate3.support.OpenSessionInViewFilter
singleSession
true
hibernateFilter
/PersonService
但是开启OpenSessionInView也有缺点:因为session关闭被延后了,而hibernate的一级缓存在session中,所以会导致大量的缓存中的数据被长时间停留在内存中。