您的位置:首页 > 编程语言 > Java开发

Spring事物传播性

2018-03-07 11:16 411 查看
Spring中事务声明方式:1、基于XML配置:在applicationContext.xml中对类的方法统一配置;2、注解式(@Transactional) 

关于配置不细说,之前博文里有写:http://angelbill3.iteye.com/blog/1896502 

在做DEMO的时候,一度发现注解式配置不起作用,后来才发现在applicationContext.xml中少了一句话,即启动Spring注解的声明。如下: 
Java代码  

<tx:annotation-driven transaction-manager="transactionManager" />  

加上之后注解式事务就能用了。 

1、注解式的方式(@Transactional注解方式)优先级要高于在applicationContext.xml中对类的方法统一配置。原因很简单,后者算是统一配置,前者是具体灵活,可单独对某个类进行配置,优先级当然要高了。 

2、Spring提供的事务管理器类有很多,在使用jdbc的抽象以及ibatis支持时可用以下类:org.springframework.jdbc.datasource.DataSourceTransactionManager 

3、Spring事务传播行为: 
propagation说明
REQUIRED如果有事务,那么加入事务,没有的话新创建一个
NOT_SUPPORTED这个方法不开启事务
REQUIREDS_NEW不管是否存在事务,都创建一个新的事务,原来的挂起,新的执行完毕,继续执行老的事务
MANDATORY必须在一个已有的事务中执行,否则抛出异常
NEVER不能在一个事务中执行,就是当前必须没有事务,否则抛出异常
SUPPORTS其他bean调用这个方法,如果在其他bean中声明了事务,就是用事务。没有声明,就不用事务。
NESTED如果一个活动的事务存在,则运行在一个嵌套的事务中,如果没有活动的事务,则按照REQUIRED属性执行,它使用一个单独的事务。这个事务拥有多个回滚的保存点,内部事务的回滚不会对外部事务造成影响,它只对DataSource TransactionManager事务管理器起效。
另还可以设: 
readOnly=true(只读事务),rollbackFor = ApplicationException.class(对具体的异常进行设置),timeout=30(超时时间),isolation=Isolation.DEFAULT(数据库隔离级别设置)等 

4、下面重点就常用的几个用注解的方试写下实例 
框架:Spring mvc + mybatis3 

4.1 REQUIRED:最常用的事务传播 

Java代码  

//ServiveA  
@Transactional (propagation = Propagation.REQUIRED )   
public void dealA(){  
    Article a = new Article();  
    a.setTitlename("1");  
    this.sql.insert("com.faj.dao.ArticleMapper.insert",a);//插入  
              
    serviceB.dealB();//调用另一个Service方法  
}  
  
//ServiceB  
@Transactional (propagation = Propagation.REQUIRED )   
public void dealB(){  
    Article a = new Article();  
    a.setTitlename("3");  
    this.sqlSession.insert("com.faj.dao.ArticleMapper.insert",a);  
    throw new ApplicationException();  
    //ApplicationException是一个继承RunTimeExcepiotn的异常处理类  
}  

//运行结果分析:------------------------------------- 
(列举主要步骤) 
以下信息是在LOG4J的DEBUG级别层打印。 

Java代码  

[DEBUG] 2013-09-09 17:06:33 :Creating new transaction with name [com.service.impl.ServiceAImpl.dealA]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT; ''  
[DEBUG] 2013-09-09 17:06:33 :Creating a new SqlSession  
[DEBUG] 2013-09-09 17:06:33 :Registering transaction synchronization for SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@54fe9ab3]  
[DEBUG] 2013-09-09 17:06:33 :==>  Preparing: insert into article (id, titlename, type, insertuser, inserttime, state, updateuser, updatetime, isdelete, indeximg, indexcontent, readcount, commit, support, content ) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? )   
  
[DEBUG] 2013-09-09 17:06:33 :Participating in existing transaction   
[DEBUG] 2013-09-09 17:06:33 :Fetched SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@54fe9ab3] from current transaction  
[DEBUG] 2013-09-09 17:06:33 :==>  Preparing: insert into article (id, titlename, type, insertuser, inserttime, state, updateuser, updatetime, isdelete, indeximg, indexcontent, readcount, commit, support, content ) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? )   
  
[DEBUG] 2013-09-09 17:17:30 :Participating transaction failed - marking existing transaction as rollback-only  
[DEBUG] 2013-09-09 17:17:30 :Setting JDBC transaction [com.mysql.jdbc.Connection@6aa0328b] rollback-only  
[DEBUG] 2013-09-09 17:17:30 :Transaction synchronization rolling back SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@54fe9ab3]  

第1行说明新建了事务,传播行为:PROPAGATION_REQUIRED 
建立一个SqlSession(54fe9ab3) 
第4行:类ServiceA的dealA方法中有insert方法,所以插入数据。 
接着就是释放了联连。(此步骤略) 

接下来就到了运行:serviceB.dealB();//调用另一个Service方法 
因为事务的传播行为是PROPAGATION_REQUIRED(如果有事务,那么加入事务,没有的话新创建一个) 
第6行:所以看出已经加入了已有的事务中了。(Participating in existing transaction) 
第8行:类ServiceB的dealB方法中有insert方法,所以插入数据,可以看出是同一个SESSIONID。 
第10行,两个方法共享一个事务,此时,已把主事务标记成了rollback-only 

类ServiceB的dealB方法中抛出unchecked异常。 
注:RunTimeException属于unchecked异常,若抛出Exception(属checked异常),不会回滚。 
所以在第12行,事务回滚。 

因为是共享事务,所以两条插入语句都会回滚。

详细理解:http://blog.csdn.net/yuanlaishini2010/article/details/45792069
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: