【spring基础】spring声明式事务详解
一、spring声明式事务
1.1 spring的事务管理器
spring没有直接管理事务,而是将管理事务的责任委托给JTA或相应的持久性机制所提供的某个特定平台的事务实现。spring容器负责事物的操作,spring容器充当切面,事务的方法称为增强处理,生成的代理对象的方法就是目标方法+增强也就是crud+事务程序员只用做crud的操作,也就是目标方法和声明哪些方法应该在事务中运行。
Spring提供了许多内置事务管理器实现:
- DataSourceTransactionManager:位于org.springframework.jdbc.datasource包中,数据源事务管理器,提供对单个javax.sql.DataSource事务管理,用于Spring JDBC抽象框架、iBATIS或MyBatis框架的事务管理;
- JdoTransactionManager:位于org.springframework.orm.jdo包中,提供对单个javax.jdo.PersistenceManagerFactory事务管理,用于集成JDO框架时的事务管理;
- JpaTransactionManager:位于org.springframework.orm.jpa包中,提供对单个javax.persistence.EntityManagerFactory事务支持,用于集成JPA实现框架时的事务管理;
- HibernateTransactionManager:位于org.springframework.orm.hibernate3包中,提供对单个org.hibernate.SessionFactory事务支持,用于集成Hibernate框架时的事务管理;该事务管理器只支持Hibernate3+版本,且Spring3.0+版本只支持Hibernate 3.2+版本;
- JtaTransactionManager:位于org.springframework.transaction.jta包中,提供对分布式事务管理的支持,并将事务管理委托给Java EE应用服务器事务管理器;
- OC4JjtaTransactionManager:位于org.springframework.transaction.jta包中,Spring提供的对OC4J10.1.3+应用服务器事务管理器的适配器,此适配器用于对应用服务器提供的高级事务的支持;
- WebSphereUowTransactionManager:位于org.springframework.transaction.jta包中,Spring提供的对WebSphere 6.0+应用服务器事务管理器的适配器,此适配器用于对应用服务器提供的高级事务的支持;
- WebLogicJtaTransactionManager:位于org.springframework.transaction.jta包中,Spring提供的对WebLogic 8.1+应用服务器事务管理器的适配器,此适配器用于对应用服务器提供的高级事务的支持。
Spring不仅提供这些事务管理器,还提供对如JMS事务管理的管理器等,Spring提供一致的事务抽象如图所示
spring与hibernate
说明:
spring在调用具体的事务管理器之前做了一些准备工作,提前设置事务的读写策略,而这些事务策略是公共的东西,是写在spring的配置文件中的,这些内容的处理需要放在抽象类中去做
二、spring与hibernate整合中的事务处理
1.1 以xml形式
引入properties配置文件
<property name="locations">
<value>classpath:jdbc.properties</value>
</property>
配置dbcp数据源
<bean id="dataSource" destroy-method="close" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="${jdbc.driverClassName}" />
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
</bean>
引入sessionfactory,使用hibernate外部配置文件
<bean id="sessionFactory2" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="configLocation">
<value>classpath:hibernate.cfg.xml</value>
</property>
</bean>
注入dao和service层
<bean id="personDao" class="cn.qjc.hibernate.dao.impl.PersonDaoImpl">
<property name="sessionFactory">
<ref bean="sessionFactory2"/>
</property>
</bean> <bean id="personService" class="cn.qjc.hibernate.service.impl.PersonServiceImpl">
<property name="personDao">
<ref bean="personDao"/>
</property>
</bean>
配置hibernate事务管理器
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory">
<ref bean="sessionFactory2"/>
</property>
</bean>
配置声明式事务
作用:
1、告诉spring容器事务管理器
2、告诉spring容器什么样的方法使用什么样的事务
<tx:advice transaction-manager="transactionManager" id="tx">
<tx:attributes>
<!--
name 目标方法的范围
islation 隔离级别
propagation 传播属性
read-only
true 只读事务
false 读写事务
-->
<tx:method name="save*" isolation="DEFAULT" propagation="REQUIRED" read-only="false"/>
</tx:attributes>
</tx:advice>
配置切入点
<aop:config>
<aop:pointcut expression="execution(* cn.qjc.hibernate.service.impl.*.*(..))" id="perform"/>
<span style="white-space:pre"> </span><!-- 将切入点应用到增强方法 -->
<aop:advisor advice-ref="tx" pointcut-ref="perform"/>
</aop:config>
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的属性,并且在配置文件中进行注入。
<bean id="hibernateTemplate" class="org.springframework.orm.hibernate3.HibernateTemplate">
<property name="sessionFactory" ref="sessionFactory2"></property>
</bean>
1.2 以注解形式
1、在配置文件中应用spring的自动扫描机制
<context:component-scan base-package="cn.qjc"/>
2、在配置文件中引入注解解析器
<tx:annotation-driven transaction-manager="transactionManager"/>
3、在service层通过@Transaction进行注解
注意:如果在类级别上被注解为只读事务,但是这个类中的方法中@Transaction注解的事务设置将优先于类级别注解的事务设置。
1.3 spring事务的传播属性
required: 业务方法需要在一个事务中运行。如果方法运行时,已经处在一个事务中,那么加入到该事务,否则为自己创建一个新事务(默认)
not-supported:spring容器不开启事务,如果方法在一个事务中被调用,该事务会被挂起,该方法结束后,事务恢复
requiresnew:不管是否存在事务,业务方法总会创建一个新事务。
mandatorky: 业务方法只能在一个已经存在的事务中执行,如果业务方法在没有事务下调用,容器抛出例外。
此外还有supports、never、nested等属性,但是通常使用默认
propagation="required" 此配置可以解决事务嵌套问题,何为事务嵌套?
比如:
在工作流框架和操作service层的某个方法中都存在事务,service层也有自己的事务,当service执行的时候,就会出现事务嵌套,即方法本身有事务,方法中的方法还有事务,这就是事务嵌套。而spring通过事务传播属性propagation="required"解决了这一问题。
1.4 OpenInSessionView
在s2sh整合以后,spring管理事务,由于使用的是spring的声明式事务处理方式,所以在调用this.getHibernateTemplate()这个方法执行完之后,session立即关闭,如果当前执行的方法有事务,当事务环境的方法被调用完毕后session关闭。所以当值在页面输出时会产生异常。
处理方式为:OpenSessionInview模式(web.xml中配置)
<filter>
<filter-name>hibernateFilter</filter-name>
<filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class> <!-- singleSession默认为true,若设置为false则等于没有OpenSessionInView -->
<init-param>
<param-name>singleSession</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>hibernateFilter</filter-name>
<url-pattern>/PersonService</url-pattern>
</filter-mapping>
从上面代码可以看出,当提交一个请求时,OpenSessionInView中已经把session开启了,在response以后才要关闭session,也就意味着有了openSessionInView必须在struts2的过滤器之前。(放struts2过滤器位置上面)
但是开启OpenSessionInView也有缺点:因为session关闭被延后了,而hibernate的一级缓存在session中,所以会导致大量的缓存中的数据被长时间停留在内存中。
【spring基础】spring声明式事务详解的更多相关文章
- Spring事务管理的实现方式之编程式事务与声明式事务详解
原创说明:本博文为原创作品,绝非他处转载,转载请联系博主 1.上篇文章讲解了Spring事务的传播级别与隔离级别,以及分布式事务的简单配置,点击回看上篇文章 2.编程式事务:编码方式实现事务管理(代码 ...
- Spring事务管理实现方式之编程式事务与声明式事务详解(转)
原文:https://blog.csdn.net/liaohaojian/article/details/70139151 编程式事务 编码方式实现事务管理(代码演示为JDBC事务管理) Spring ...
- Spring笔记(4) - Spring的编程式事务和声明式事务详解
一.背景 事务管理对于企业应用而言至关重要.它保证了用户的每一次操作都是可靠的,即便出现了异常的访问情况,也不至于破坏后台数据的完整性.就像银行的自助取款机,通常都能正常为客户服务,但是也难免遇到操作 ...
- Spring AOP实现声明式事务代码分析
众所周知,Spring的声明式事务是利用AOP手段实现的,所谓"深入一点,你会更快乐",本文试图给出相关代码分析. AOP联盟为增强定义了org.aopalliance.aop.A ...
- SSM实战——秒杀系统之Service层接口设计与实现、Spring托管、声明式事务
一:Service层接口设计 准备工作:新建三个包:service包.exception包.dto包,分别用来存放业务接口.自定义异常类.dto类. 1:定义接口 package org.myseck ...
- Spring—SSJ集成&声明式事务管理
1. 课程介绍 1. SSJ集成;(掌握) 2. 声明式事务管理;(掌握) 什么是三大框架 2.1. ssh Struts/Struts2 Spring Hibernate 2.2. ss ...
- 11、Spring教程之声明式事务
1.回顾事务 事务在项目开发过程非常重要,涉及到数据的一致性的问题,不容马虎! 事务管理是企业级应用程序开发中必备技术,用来确保数据的完整性和一致性. 事务就是把一系列的动作当成一个独立的工作单元,这 ...
- Spring(四)-声明式事务
Spring-04 声明式事务 1.事务的定义 事务就是由一组逻辑上紧密关联的多个工作单元(数据库操作)而合并成一个整体,这些操作要么都执行,要么都不执行. 2.事务的特性:ACID 1)原子性A : ...
- Spring笔记(5) - 声明式事务@EnableTransactionManagement注解源码分析
一.背景 前面详解了实现Spring事务的两种方式的不同实现:编程式事务和声明式事务,对于配置都使用到了xml配置,今天介绍Spring事务的注解开发,例如下面例子: 配置类:注册数据源.JDBC模板 ...
随机推荐
- 一个简单的使用Quartz和Oozie调度作业给大数据计算平台执行
一,介绍 Oozie是一个基于Hadoop的工作流调度器,它可以通过Oozie Client 以编程的形式提交不同类型的作业,如MapReduce作业和Spark作业给底层的计算平台(如 Cloude ...
- 在O(n) 时间复杂度,O(1)空间复杂度内反转单链表
在LeetCode中看到判断回文的程序:https://leetcode.com/problems/palindrome-linked-list/ 里面用单链表来存储数据,先反转前半部分的单链表,然后 ...
- 法律AI数据及应用
本文简单列举了法律AI目前的应用,数据集,研究方向. 历史 1970年,Buchanan和Headrick发表文章"关于人工智能和法律推理的一些猜测",讨论了对法律研究和推理进行建 ...
- caffe 中 python 数据层
caffe中大多数层用C++写成. 但是对于自己数据的输入要写对应的输入层,比如你要去图像中的一部分,不能用LMDB,或者你的label 需要特殊的标记. 这时候就需要用python 写一个输入层. ...
- Java EE之Hibernate异常总结【3】Disabling contextual LOB creation as createClob() method threw error java.lang.reflect.InvocationTargetException
参考文献:https://stackoverflow.com/questions/4588755/disabling-contextual-lob-creation-as-createclob-met ...
- uboot 如何向内核传递参数
a.uboot 向内核传递的参数有两种类型 1.一个是bootargs 2.一个是环境参数, 而环境参数的设置靠的是 Y:\junda\JdLinuxApp\A1801_uboot\source\u- ...
- ResNet152网络复现(Caffe)
一.准备数据集 1) 下载数据集 Imagnet网站上下载了三类图片,分别是big cat.dog.fish,其中训练集的图片数一共是4149,测试集的图片数是1003,训练集和测试集的图片数比例4 ...
- Django开发笔记三
Django开发笔记一 Django开发笔记二 Django开发笔记三 Django开发笔记四 Django开发笔记五 Django开发笔记六 1.基于类的方式重写登录:views.py: from ...
- dataTable插件锁表头和锁列的教程
源代码下载 我的同事让我帮忙给弄个锁头锁列的插件.结果找到大名鼎鼎的jquery dataTable插件. 今天我们来介绍不常用的功能:dataTable插件锁表头和锁前两列 由于是移动前端.我们不考 ...
- 分布式系列 - dubbo服务telnet命令【转】
dubbo服务发布之后,我们可以利用telnet命令进行调试.管理.Dubbo2.0.5以上版本服务提供端口支持telnet命令,下面我以通过实例抛砖引玉一下: 1.连接服务 测试对应IP和端口下的d ...