为什么transactional 回滚注解

1663人阅读
&?xml version=&1.0& encoding=&UTF-8&?&
xmlns=&http://www.springframework.org/schema/beans&
xmlns:xsi=&http://www.w3.org/2001/XMLSchema-instance&
xmlns:context=&http://www.springframework.org/schema/context&
xmlns:jaxws=&http://cxf.apache.org/jaxws&
xmlns:aop=&http://www.springframework.org/schema/aop&
xmlns:tx=&http://www.springframework.org/schema/tx&
xmlns:http-conf=&http://cxf.apache.org/transports/http/configuration&
xsi:schemaLocation=&http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.2.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
http://cxf.apache.org/transports/http/configuration
http://cxf.apache.org/schemas/configuration/http-conf.xsd&&
&context:component-scan base-package=&com.sdh.demo.service, com.sdh.demo.dao& /&
&!-- 数据源 --&
&bean id=&dataSource& class=&com.alibaba.druid.pool.DruidDataSource&
init-method=&init& destroy-method=&close&&
&property name=&url& value=&${database.url}& /&
&property name=&username& value=&${database.username}& /&
&property name=&password& value=&${database.password}& /&
&property name=&initialSize& value=&${database.initialSize}& /&
&property name=&maxActive& value=&${database.maxActive}& /&
&property name=&minIdle& value=&${database.minIdle}& /&
&property name=&testWhileIdle& value=&${database.testWhileIdle}& /&
&property name=&testOnBorrow& value=&${database.testOnBorrow}& /&
&property name=&validationQuery& value=&${database.validationQuery}& /&
&!-- 配置监控统计拦截的filters --&
&property name=&filters& value=&wall,stat& /&
&bean id=&sessionFactory& class=&org.springframework.orm.hibernate4.LocalSessionFactoryBean&&
&property name=&dataSource& ref=&dataSource& /&
&property name=&hibernateProperties&&
&prop key=&hibernate.dialect&&org.hibernate.dialect.MySQLInnoDBDialect&/prop&
&prop key=&hibernate.show_sql&&true&/prop&
&prop key=&hibernate.format_sql&&false&/prop&
&/property&
&property name=&packagesToScan& value=&com.sdh.demo.bean& /&
&!-- 配置一个事务管理器 --&
&bean id=&transactionManager& class=&org.springframework.orm.hibernate4.HibernateTransactionManager&&
&property name=&sessionFactory& ref=&sessionFactory& /&
&!-- 配置 Annotation 驱动,扫描@Transactional注解的类定义事务 --&
&tx:annotation-driven transaction-manager=&transactionManager& proxy-target-class=&true& /&
在接口或类的声明处 ,写一个@Transactional.
要是只在接口上写, 接口的实现类就会继承下来、接口的实现类的具体方法,可以覆盖类声明处的设置
@Transactional &&//类级的注解、适用于类中所有的public的方法
事务的传播行为和隔离级别
大家在使用spring的注解式事务管理时,对事务的传播行为和隔离级别可能有点不知所措,下边就详细的介绍下以备方便查阅。
事物注解方式: @Transactional
当标于类前时, 标示类中所有方法都进行事物处理&,&例子:
@Transactional&
public&class&TestServiceBean&implements&TestService {}
当类中某些方法不需要事物时:
@Transactional&
public&class&TestServiceBean&implements&TestService {
private&TestD&
public&void&setDao(TestDao dao) {&this.dao =& } @Transactional(propagation&=Propagation.NOT_SUPPORTED)&
public&ListgetAll() {&return&null; }&
事物传播行为介绍:&
@Transactional(propagation=Propagation.REQUIRED)&
如果有事务, 那么加入事务, 没有的话新建一个(默认情况下)
@Transactional(propagation=Propagation.NOT_SUPPORTED)&
容器不为这个方法开启事务
@Transactional(propagation=Propagation.REQUIRES_NEW)&
不管是否存在事务,都创建一个新的事务,原来的挂起,新的执行完毕,继续执行老的事务
@Transactional(propagation=Propagation.MANDATORY)&
必须在一个已有的事务中执行,否则抛出异常
@Transactional(propagation=Propagation.NEVER)&
必须在一个没有的事务中执行,否则抛出异常(与Propagation.MANDATORY相反)
@Transactional(propagation=Propagation.SUPPORTS)&
如果其他bean调用这个方法,在其他bean中声明事务,那就用事务.如果其他bean没有声明事务,那就不用事务.
事物超时设置:
@Transactional(timeout=30) //默认是30秒
事务隔离级别:
@Transactional(isolation = Isolation.READ_UNCOMMITTED)
读取未提交数据(会出现脏读, 不可重复读) 基本不使用
@Transactional(isolation = Isolation.READ_COMMITTED)
读取已提交数据(会出现不可重复读和幻读)
@Transactional(isolation = Isolation.REPEATABLE_READ)
可重复读(会出现幻读)
@Transactional(isolation = Isolation.SERIALIZABLE)
MYSQL: 默认为REPEATABLE_READ级别
SQLSERVER: 默认为READ_COMMITTED
脏读&: 一个事务读取到另一事务未提交的更新数据
不可重复读&: 在同一事务中, 多次读取同一数据返回的结果有所不同, 换句话说,&
后续读取可以读到另一事务已提交的更新数据. 相反, &可重复读&在同一事务中多次
读取数据时, 能够保证所读数据一样, 也就是后续读取不能读到另一事务已提交的更新数据
幻读&: 一个事务读到另一个事务已提交的insert数据
@Transactional注解中常用参数说明
参 数 名 称
功 能 描 述
该属性用于设置当前事务是否为只读事务,设置为true表示只读,false则表示可读写,默认值为false。例如:@Transactional(readOnly=true)
rollbackFor
该属性用于设置需要进行回滚的异常类数组,当方法中抛出指定异常数组中的异常时,则进行事务回滚。例如:
指定单一异常类:@Transactional(rollbackFor=RuntimeException.class)
指定多个异常类:@Transactional(rollbackFor={RuntimeException.class, Exception.class})
参 数 名 称
功 能 描 述
rollbackForClassName
该属性用于设置需要进行回滚的异常类名称数组,当方法中抛出指定异常名称数组中的异常时,则进行事务回滚。例如:
指定单一异常类名称:@Transactional(rollbackForClassName=&RuntimeException&)
指定多个异常类名称:@Transactional(rollbackForClassName={&RuntimeException&,&Exception&})
noRollbackFor
该属性用于设置不需要进行回滚的异常类数组,当方法中抛出指定异常数组中的异常时,不进行事务回滚。例如:
指定单一异常类:@Transactional(noRollbackFor=RuntimeException.class)
指定多个异常类:@Transactional(noRollbackFor={RuntimeException.class, Exception.class})
noRollbackForClassName
该属性用于设置不需要进行回滚的异常类名称数组,当方法中抛出指定异常名称数组中的异常时,不进行事务回滚。例如:
指定单一异常类名称:@Transactional(noRollbackForClassName=&RuntimeException&)
指定多个异常类名称:
@Transactional(noRollbackForClassName={&RuntimeException&,&Exception&})
propagation
该属性用于设置事务的传播行为,具体取值可参考表6-7。
例如:@Transactional(propagation=Propagation.NOT_SUPPORTED,readOnly=true)
该属性用于设置底层数据库的事务隔离级别,事务隔离级别用于处理多事务并发的情况,通常使用数据库的默认隔离级别即可,基本不需要进行设置
该属性用于设置事务的超时秒数,默认值为-1表示永不超时
注意的几点:
1 @Transactional 只能被应用到public方法上, 对于其它非public的方法,如果标记了@Transactional也不会报错,但方法没有事务功能.
2用 spring 事务管理器,由spring来负责数据库的打开,提交,回滚.默认遇到运行期例外(throw new RuntimeException(&注释&);)会回滚,即遇到不受检查(unchecked)的例外时回滚;而遇到需要捕获的例外(throw new Exception(&注释&);)不会回滚,即遇到受检查的例外(就是非运行时抛出的异常,编译器会检查到的异常叫受检查例外或说受检查异常)时,需我们指定方式来让事务回滚要想所有异常都回滚,要加上 @Transactional( rollbackFor={Exception.class,其它异常})
.如果让unchecked例外不回滚: @Transactional(notRollbackFor=RunTimeException.class)
@Transactional(rollbackFor=Exception.class) //指定回滚,遇到异常Exception时回滚
public void methodName() {
throw new Exception(&注释&);
@Transactional(noRollbackFor=Exception.class)//指定不回滚,遇到运行期例外(throw new RuntimeException(&注释&);)会回滚
public ItimDaoImpl getItemDaoImpl() {
throw new RuntimeException(&注释&);
3、@Transactional 注解应该只被应用到 public 可见度的方法上。&如果你在 protected、private 或者 package-visible 的方法上使用 @Transactional 注解,它也不会报错, 但是这个被注解的方法将不会展示已配置的事务设置。
4、@Transactional 注解可以被应用于接口定义和接口方法、类定义和类的 public 方法上。然而,请注意仅仅 @Transactional 注解的出现不足于开启事务行为,它仅仅 是一种元数据,能够被可以识别 @Transactional 注解和上述的配置适当的具有事务行为的beans所使用。上面的例子中,其实正是 元素的出现 开启 了事务行为。
5、Spring团队的建议是你在具体的类(或类的方法)上使用 @Transactional 注解,而不要使用在类所要实现的任何接口上。你当然可以在接口上使用 @Transactional 注解,但是这将只能当你设置了基于接口的代理时它才生效。因为注解是不能继承的,这就意味着如果你正在使用基于类的代理时,那么事务的设置将不能被基于类的代理所识别,而且对象也将不会被事务代理所包装(将被确认为严重的)。因此,请接受Spring团队的建议并且在具体的类上使用 @Transactional 注解。
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:2394次
排名:千里之外> 博客详情
先让我们看代码吧! 以下代码为在“”基础上修改。首先修改applicationContext.xml如下:
&!-- 定义一个数据源 --&
&bean id="dataSource" class="org.apache.tomcat.jdbc.pool.DataSource"&
&property name="driverClassName" value="com.mysql.jdbc.Driver" /&
&property name="url" value="jdbc:mysql://localhost:3306/spring_test" /&
&property name="username" value="root" /&
&property name="password" value="root" /&
&!-- 定义JdbcTemplate的Bean --&
&bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"
p:dataSource-ref="dataSource"&
&!-- 配置事务管理器 --&
&bean id="txManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager"
p:dataSource-ref="dataSource"&
&!-- enables scanning for @Transactional annotations --&
&tx:annotation-driven transaction-manager="txManager" /&
&!-- 在该Bean的代码中标注@Transactional可以被事务管理器注入 --&
&bean id="userScore"
class="net.hingyi.springDemo.transaction.service.UserScoreServiceImpl"
p:userScoreRepository-ref="userScoreRepository_jdbc" /&
&bean id="userScoreRepository_jdbc"
class="net.hingyi.springDemo.transaction.repository.UserScoreRepositoryImpl"
p:jdbcTemplate-ref="jdbcTemplate" /&
&实现类代码:
@Transactional
public class UserScoreRepositoryImpl implements UserScoreRepository {
private JdbcTemplate jdbcT
public UserScore getUserSocore(String userNo) {
final UserScore us = new UserScore();
OK了!以上就实现了简单的事务管理了。现在再稍微了解下@Transactional。 在配置文件中,默认情况下,&tx:annotation-driven&会自动使用名称为transactionManager的事务管理器。所以,如果定义的事务管理器名称为transactionManager,那么就可以直接使用&tx:annotation-driven/&。如下:
&!-- 配置事务管理器 --&
&bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager"
p:dataSource-ref="dataSource"&
&!-- enables scanning for @Transactional annotations --&
&tx:annotation-driven/&
&tx:annotation-driven&一共有四个属性如下,
mode:指定Spring事务管理框架创建通知bean的方式。可用的值有proxy和aspectj。前者是默认值,表示通知对象是个JDK代理;后者表示Spring AOP会使用AspectJ创建代理
proxy-target-class:如果为true,Spring将创建子类来代理业务类;如果为false,则使用基于接口的代理。(如果使用子类代理,需要在类路径中添加CGLib.jar类库)
order:如果业务类除事务切面外,还需要织入其他的切面,通过该属性可以控制事务切面在目标连接点的织入顺序。
transaction-manager:指定到现有的PlatformTransaction Manager bean的引用,通知会使用该引用
&@Transactional的属性
枚举org.springframework.transaction.annotation.Isolation的值
事务隔离级别
noRollbackFor
Class&? extends Throwable&[]
一组异常类,遇到时不回滚。默认为{}
noRollbackForClassName
一组异常类名,遇到时不回滚,默认为{}
propagation
枚举org.springframework.transaction.annotation.Propagation的值
事务传播行为
事务读写性
rollbackFor
Class&? extends Throwable&[]
一组异常类,遇到时回滚
rollbackForClassName
一组异常类名,遇到时回滚
超时时间,以秒为单位
可选的限定描述符,指定使用的事务管理器
@Transactional标注的位置 @Transactional注解可以标注在类和方法上,也可以标注在定义的接口和接口方法上。 如果我们在接口上标注@Transactional注解,会留下这样的隐患:因为注解不能被继承,所以业务接口中标注的@Transactional注解不会被业务实现类继承。所以可能会出现不启动事务的情况。所以,Spring建议我们将@Transaction注解在实现类上。 在方法上的@Transactional注解会覆盖掉类上的@Transactional。
使用不同的事务管理器 如果我们要程序中使用多个事务管理器(主要是针对多数据源的情况),可以通过以下的方式实现: Service代码:
public class MultiTxService {
@Transactional("tran_1")
public void addTest(int id){
@Transactional("tran_2")
public void deleteTest(int id){
applicationContext.xml配置如下:&
&bean id="tran_1"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager"
p:dataSource-ref="dataSource"&
&qualifier value="tran_1"/&
&bean id="tran_2"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager"
p:dataSource-ref="dataSource"&
&qualifier value="tran_2"/&
经过以上的代码,每个事务都会绑定各自的独立的数据源,进行各自的事务管理。我们可以优化下以上代码,可以自定义一个绑定到特定事务管理器的注解,然后直接使用这个自定义的注解进行标识:
@Target({ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Transactional("tran_1")
public @interface CustomerTransactional {
在Service代码中使用:
//使用名为tran_1的事务管理器
@CustomerTransactional
public void addTest(String str){
人打赏支持
参与源创会
领取时间:
“”在线下联结了各位 OSCer,推广开源项目和理念,很荣幸有你的参与~
领取条件:参与过开源中国“源创会”的 OSCer 可以领取
码字总数 13042
支付宝支付
微信扫码支付
打赏金额: ¥
已支付成功
打赏金额: ¥
& 开源中国(OSChina.NET) |
开源中国社区(OSChina.net)是工信部
指定的官方社区&&等spring同步关键词synchronized和事务锁@Transactional为什么还有并发?
@Transactional
@Service(&projFcd&)
public class ProjFcdImpl implements ProjFcd {
public synchronized Result investProject(InvestProjBO tp) throws ProjException {
}一个service类上加了@Transaction注解,在方法上加了synchronized关键字,可是最后还是发生了并发问题,是事务没配好,还是怎么回事?再问一句这里的事务锁和同步锁的进入出来顺序是怎么样的?1个牛币所有回答列表(6)是不是并发的时候,主键不一样了?ProjFcdImpl的scope不是配的singleton吗?试试配成 prototype@Transactional(isolation = Isolation.SERIALIZABLE)指定事务隔离级别可以解决你的问题。贴出里面业务详细代码&LV2如果应用是集群的就有可能并发呀!@Transactional &synchronized&要分开使用,因为加上@Transactional&spring AOP管理事务时,synchronized&并不起作用,可以新建一个不带事务的同步方法,该同步方法在调用investProject(InvestProjBO tp)方法。之前遇到过这种问题,可以尝试一下这样做。完等等等等完等等完等等等最热搜索问答话题编程语言基础Web开发数据库开发客户端开发脚本工具游戏开发服务器软硬件开源组件类库相关问答等等等等等完完等完等完等最近浏览暂无贡献等级暂无贡献等级暂无贡献等级暂无贡献等级暂无贡献等级暂无贡献等级暂无贡献等级暂无贡献等级暂无贡献等级扫描二维码关注最代码为好友"/>扫描二维码关注最代码为好友Spring 使用Spring注解方式管理事务与传播行为 -
- ITeye技术网站
博客分类:
// 业务方法需要在一个事物中运行,如果方法运行时,已经存在一个事物中,
// 那么加入该事物,否则为自己创建一个新事物。
@Transactional(propagation = Propagation.REQUIRED)
public void test1() {
// 声明方法不需要事务,如果方法没有关联到一个事务,容器不会为它开启事物。
// 如果方法在一个事物中被调用,该事物会被挂起,在方法调用结束后,原先的
// 事物便会恢复执行。
@Transactional(propagation = Propagation.NOT_SUPPORTED)
public void test2() {
// 表明不管是否存在事物,业务方法总会为自己发起一个新事物。
// 如果方法已经运行在一个事物中,则原有事物会被挂起,
// 新的事物会被创建,直到方法执行结束,新事物才算结束,
// 原先的事务才会被恢复执行。
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void test3() {
// 该属性指定业务方法只能在一个已经存在的事物中执行,
// 业务方法不能发起自己的事物,如果业务方法在没有事物的环境
// 下调用,容器就会抛出异常。
@Transactional(propagation = Propagation.MANDATORY)
public void test4() {
// 这个事物属性表明,如果业务方法在某个事务范围内被调用,则方法成为该事物的一部分,
// 如果业务方法在事务范围外被调用,则方法在没有事物的环境下执行。
@Transactional(propagation = Propagation.SUPPORTS)
public void test5() {
// 指定业务方法绝对不能在事物范围内执行。如果业务方法在某个事物中执行,
// 容器会抛出异常,只有业务方法没有关联到任何事物,才能正常执行。
@Transactional(propagation = Propagation.NEVER)
public void test6() {
// 如果一个活动的事物存在,则运行在一个嵌套的事物中,如果没有活动事物,
// 则按REQUIRED属性执行,它使用了一个单独的事物,这个事物拥有多个回滚的保存点,
// 内部事务的回滚不会对外事物造成影响,它只对DataSourceTransactionManager
// 事务管理器起效。
@Transactional(propagation = Propagation.NESTED)
public void test7() {
@Transactional(isolation = Isolation.DEFAULT)
public void test8() {
// 读已提交数据(会出现不可重复读和幻读)
@Transactional(isolation = Isolation.READ_COMMITTED)
public void test9() {
// 读未提交数据(会出现脏读、不可重复读和幻读)
@Transactional(isolation = Isolation.READ_UNCOMMITTED)
public void test10() {
// 可重复读(会出现幻读)
@Transactional(isolation = Isolation.REPEATABLE_READ)
public void test11() {
@Transactional(isolation = Isolation.SERIALIZABLE)
public void test12() {
// 抛出Exception异常时,记录回滚
@Transactional(rollbackFor = Exception.class)
public void test13() throws Exception {
浏览: 175861 次
来自: 杭州
/portfolios/ ...
感谢,正在学习oAuth,有机会一起交流
你好,lightvodcode.zip现在不能下了,能否发我一 ...
&div style=&text-al ...
解决了,不能用
DiskFileItemFactory fac ...[架构设计] spring,mybatis事务管理配置与@Transactional注解使用 | IT知识库
-& 正文阅读
[架构设计]spring,mybatis事务管理配置与@Transactional注解使用
spring,mybatis事务管理配置与@Transactional注解使用
概述事务管理对于企业应用来说是至关重要的,即使出现异常情况,它也可以保证数据的一致性。Spring Framework对事务管理提供了一致的抽象,其特点如下:为不同的事务API提供一致的编程模型,比如JTA(Java Transaction API), JDBC, Hibernate, JPA(Java Persistence API和JDO(Java Data Objects)
支持声明式事务管理,特别是基于注解的声明式事务管理,简单易用
提供比其他事务API如JTA更简单的编程式事务管理API
与spring数据访问抽象的完美集成事务管理方式spring支持编程式事务管理和声明式事务管理两种方式。编程式事务管理使用TransactionTemplate或者直接使用底层的PlatformTransactionManager。对于编程式事务管理,spring推荐使用TransactionTemplate。声明式事务管理建立在AOP之上的。其本质是对方法前后进行拦截,然后在目标方法开始之前创建或者加入一个事务,在执行完目标方法之后根据执行情况提交或者回滚事务。声明式事务最大的优点就是不需要通过编程的方式管理事务,这样就不需要在业务逻辑代码中掺杂事务管理的代码,只需在配置文件中做相关的事务规则声明(或通过基于@Transactional注解的方式),便可以将事务规则应用到业务逻辑中。显然声明式事务管理要优于编程式事务管理,这正是spring倡导的非侵入式的开发方式。声明式事务管理使业务代码不受污染,一个普通的POJO对象,只要加上注解就可以获得完全的事务支持。和编程式事务相比,声明式事务唯一不足地方是,后者的最细粒度只能作用到方法级别,无法做到像编程式事务那样可以作用到代码块级别。但是即便有这样的需求,也存在很多变通的方法,比如,可以将需要进行事务管理的代码块独立为方法等等。声明式事务管理也有两种常用的方式,一种是基于tx和aop名字空间的xml配置文件,另一种就是基于@Transactional注解。显然基于注解的方式更简单易用,更清爽。自动提交(AutoCommit)与连接关闭时的是否自动提交自动提交默认情况下,数据库处于自动提交模式。每一条语句处于一个单独的事务中,在这条语句执行完毕时,如果执行成功则隐式的提交事务,如果执行失败则隐式的回滚事务。对于正常的事务管理,是一组相关的操作处于一个事务之中,因此必须关闭数据库的自动提交模式。不过,这个我们不用担心,spring会将底层连接的自动提交特性设置为false。org/springframework/jdbc/datasource/DataSourceTransactionManager.java
// switch to manual commit if necessary. this is very expensive in some jdbc drivers,
// so we don't want to do it unnecessarily (for example if we've explicitly
// configured the connection pool to set it already).
if (con.getautocommit()) {
&&&&txobject.setmustrestoreautocommit(true);
&&&&if (logger.isdebugenabled()) {
&&&&&&&&logger.debug("switching jdbc connection [" + con + "] to manual commit");
&&&&con.setautocommit(false);
有些数据连接池提供了关闭事务自动提交的设置,最好在设置连接池时就将其关闭。但C3P0没有提供这一特性,只能依靠spring来设置。因为JDBC规范规定,当连接对象建立时应该处于自动提交模式,这是跨DBMS的缺省值,如果需要,必须显式的关闭自动提交。C3P0遵守这一规范,让客户代码来显式的设置需要的提交模式。连接关闭时的是否自动提交当一个连接关闭时,如果有未提交的事务应该如何处理?JDBC规范没有提及,C3P0默认的策略是回滚任何未提交的事务。这是一个正确的策略,但JDBC驱动提供商之间对此问题并没有达成一致。C3P0的autoCommitOnClose属性默认是false,没有十分必要不要动它。或者可以显式的设置此属性为false,这样会更明确。基于注解的声明式事务管理配置spring-servlet.xml
&!-- transaction support--&
&!-- PlatformTransactionMnager --&
&bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"&
&&&&&property name="dataSource" ref="dataSource" /&
&!-- enable transaction annotation support --&
&tx:annotation-driven transaction-manager="txManager" /&
还要在spring-servlet.xml中添加tx名字空间
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
MyBatis自动参与到spring事务管理中,无需额外配置,只要org.mybatis.spring.SqlSessionFactoryBean引用的数据源与DataSourceTransactionManager引用的数据源一致即可,否则事务管理会不起作用。另外需要下载依赖包aopalliance.jar放置到WEB-INF/lib目录下。否则spring初始化时会报异常java.lang.NoClassDefFoundError: org/aopalliance/intercept/MethodInterceptorspring事务特性spring所有的事务管理策略类都继承自org.springframework.transaction.PlatformTransactionManager接口
public interface PlatformTransactionManager {
&&TransactionStatus getTransaction(TransactionDefinition definition)
&&&&throws TransactionE
&&void commit(TransactionStatus status) throws TransactionE
&&void rollback(TransactionStatus status) throws TransactionE
其中TransactionDefinition接口定义以下特性:事务隔离级别隔离级别是指若干个并发的事务之间的隔离程度。TransactionDefinition 接口中定义了五个表示隔离级别的常量:TransactionDefinition.ISOLATION_DEFAULT:这是默认值,表示使用底层数据库的默认隔离级别。对大部分数据库而言,通常这值就是TransactionDefinition.ISOLATION_READ_COMMITTED。
TransactionDefinition.ISOLATION_READ_UNCOMMITTED:该隔离级别表示一个事务可以读取另一个事务修改但还没有提交的数据。该级别不能防止脏读,不可重复读和幻读,因此很少使用该隔离级别。比如PostgreSQL实际上并没有此级别。
TransactionDefinition.ISOLATION_READ_COMMITTED:该隔离级别表示一个事务只能读取另一个事务已经提交的数据。该级别可以防止脏读,这也是大多数情况下的推荐值。
TransactionDefinition.ISOLATION_REPEATABLE_READ:该隔离级别表示一个事务在整个过程中可以多次重复执行某个查询,并且每次返回的记录都相同。该级别可以防止脏读和不可重复读。
TransactionDefinition.ISOLATION_SERIALIZABLE:所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰,也就是说,该级别可以防止脏读、不可重复读以及幻读。但是这将严重影响程序的性能。通常情况下也不会用到该级别。事务传播行为所谓事务的传播行为是指,如果在开始当前事务之前,一个事务上下文已经存在,此时有若干选项可以指定一个事务性方法的执行行为。在TransactionDefinition定义中包括了如下几个表示传播行为的常量:TransactionDefinition.PROPAGATION_REQUIRED:如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务。这是默认值。
TransactionDefinition.PROPAGATION_REQUIRES_NEW:创建一个新的事务,如果当前存在事务,则把当前事务挂起。
TransactionDefinition.PROPAGATION_SUPPORTS:如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式继续运行。
TransactionDefinition.PROPAGATION_NOT_SUPPORTED:以非事务方式运行,如果当前存在事务,则把当前事务挂起。
TransactionDefinition.PROPAGATION_NEVER:以非事务方式运行,如果当前存在事务,则抛出异常。
TransactionDefinition.PROPAGATION_MANDATORY:如果当前存在事务,则加入该事务;如果当前没有事务,则抛出异常。
TransactionDefinition.PROPAGATION_NESTED:如果当前存在事务,则创建一个事务作为当前事务的嵌套事务来运行;如果当前没有事务,则该取值等价于TransactionDefinition.PROPAGATION_REQUIRED。事务超时所谓事务超时,就是指一个事务所允许执行的最长时间,如果超过该时间限制但事务还没有完成,则自动回滚事务。在 TransactionDefinition 中以 int 的值来表示超时时间,其单位是秒。默认设置为底层事务系统的超时值,如果底层数据库事务系统没有设置超时值,那么就是none,没有超时限制。事务只读属性只读事务用于客户代码只读但不修改数据的情形,只读事务用于特定情景下的优化,比如使用Hibernate的时候。默认为读写事务。spring事务回滚规则指示spring事务管理器回滚一个事务的推荐方法是在当前事务的上下文内抛出异常。spring事务管理器会捕捉任何未处理的异常,然后依据规则决定是否回滚抛出异常的事务。默认配置下,spring只有在抛出的异常为运行时unchecked异常时才回滚该事务,也就是抛出的异常为RuntimeException的子类(Errors也会导致事务回滚),而抛出checked异常则不会导致事务回滚。可以明确的配置在抛出那些异常时回滚事务,包括checked异常。也可以明确定义那些异常抛出时不回滚事务。还可以编程性的通过setRollbackOnly()方法来指示一个事务必须回滚,在调用完setRollbackOnly()后你所能执行的唯一操作就是回滚。@Transactional注解@Transactional属性&
属性类型描述
可选的限定描述符,指定使用的事务管理器
propagation
enum: Propagation
可选的事务传播行为设置
enum: Isolation
可选的事务隔离级别设置
读写或只读事务,默认读写
int (in seconds granularity)
事务超时时间设置
rollbackFor
Class对象数组,必须继承自Throwable
导致事务回滚的异常类数组
rollbackForClassName
类名数组,必须继承自Throwable
导致事务回滚的异常类名字数组
noRollbackFor
Class对象数组,必须继承自Throwable
不会导致事务回滚的异常类数组
noRollbackForClassName
类名数组,必须继承自Throwable
不会导致事务回滚的异常类名字数组用法@Transactional 可以作用于接口、接口方法、类以及类方法上。当作用于类上时,该类的所有 public 方法将都具有该类型的事务属性,同时,我们也可以在方法级别使用该标注来覆盖类级别的定义。虽然 @Transactional 注解可以作用于接口、接口方法、类以及类方法上,但是 Spring 建议不要在接口或者接口方法上使用该注解,因为这只有在使用基于接口的代理时它才会生效。另外, @Transactional 注解应该只被应用到 public 方法上,这是由 Spring AOP 的本质决定的。如果你在 protected、private 或者默认可见性的方法上使用 @Transactional 注解,这将被忽略,也不会抛出任何异常。默认情况下,只有来自外部的方法调用才会被AOP代理捕获,也就是,类内部方法调用本类内部的其他方法并不会引起事务行为,即使被调用方法使用@Transactional注解进行修饰。
@Transactional(readOnly = true)
public class DefaultFooService implements FooService {
&&public Foo getFoo(String fooName) {
&&&&// do something
&&// these settings have precedence for this method
&&//方法上注解属性会覆盖类注解上的相同属性
&&@Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW)
&&public void updateFoo(Foo foo) {
&&&&// do something
》》源码地址获取springmvc + mybatis整合详细,及遇到的问题请参看以下资料:参考资料:http://www.springmvc,net/detail/6074493.htmlhttp://my.oschina.net/wangbiglei/blog/489583http://my.oschina.net/wangbiglei/blog/489604
加: 16:01:30&
更: 16:01:32&
&&网站联系: qq: email:&}

我要回帖

更多关于 transactional memory 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信