spring 中常用的两种事务配置方式以及事务的传播性、隔离级别

一、注解式事务

1、事务配置实例

(1)、spring+mybatis 事务配置

		<!-- 定义事务管理器 -->
		<bean id="transactionManager"
			class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
			<property name="dataSource" ref="dataSource" />
		</bean>
		<!--使用注释事务 -->
		<tx:annotation-driven  transaction-manager="transactionManager" />

(2)、spring+hibernate 事务配置

	<!-- 事务管理器配置,单数据源事务 -->
	<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
		<property name="sessionFactory" ref="sessionFactory" />
	</bean>
	
	<!-- 使用annotation定义事务 -->
	<tx:annotation-driven  transaction-manager="transactionManager"   proxy-target-class="true" />

看到上面的这两段配置文件是不是很熟悉,对的这就是我们平时看到的事务的配置,在spring的配置中配置数据源即dataSource、事务管理器,事务管理器使用不同的orm框架事务管理器类就不同,比如这里使用的是mybatis 所以是
org.springframework.jdbc.datasource.DataSourceTransactionManager
如果使用hibernate 则事务管理器类为
org.springframework.orm.hibernate3.HibernateTransactionManager

2、这是使用注解方式时要配置的,代码中的具体的注解以及事务的传播性、隔离级别一般在service 层中配置下面看看
@Transactional

(1)、这里说明一下,有的把这个注解放在类名称上面了,这样你配置的这个@Transactional 对这个类中的所有public方法都起作用

(2)、@Transactional 方法方法名上,只对这个方法有作用,同样必须是public的方法
比如这里就对这个方法定义了一个事务同时设置了很多属性:

	@Transactional(propagation=Propagation.REQUIRED,rollbackFor=Exception.class,timeout=1,isolation=Isolation.DEFAULT)
	public void saveUser(Map<String, String> map) throws Exception {
         System.out.println("方法开始");
		for (int i = 0; i < 500000; i++) {
	            System.out.println("*");
	        }
		 System.out.println("进入保存");
		 userDao.saveUser(map);
		 System.out.println("退出保存");
	}

事物配置中有哪些属性可以配置
(1)、事务的传播性:@Transactional(propagation=Propagation.REQUIRED)

  如果有事务, 那么加入事务, 没有的话新建一个(默认情况下)

(2)、事务的超时性:@Transactional(timeout=30) //默认是30秒

  注意这里说的是事务的超时性而不是Connection的超时性,这两个是有区别的

(3)、事务的隔离级别:@Transactional(isolation = Isolation.READ_UNCOMMITTED)

  读取未提交数据(会出现脏读, 不可重复读) 基本不使用

(4)、回滚:

	指定单一异常类:@Transactional(rollbackFor=RuntimeException.class)

	指定多个异常类:@Transactional(rollbackFor={RuntimeException.class, Exception.class})

	该属性用于设置需要进行回滚的异常类数组,当方法中抛出指定异常数组中的异常时,则进行事务回滚。

(5)、只读:@Transactional(readOnly=true)

该属性用于设置当前事务是否为只读事务,设置为true表示只读,false则表示可读写,默认值为false。

ok 这种注解方式实现事务的配置以及一些属性的定义,其实事务的东西还有很多要注意的事项,如果要深入学习的话要学习的东西还很多,这里只是简单记录一下

需要注意的方面

1、在spring配置文件中引入tx:命名空间:xmlns:tx=“http://www.springframework.org/schema/tx”
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.2.xsd
如:

<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	 xmlns:tx="http://www.springframework.org/schema/tx"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:aop="http://www.springframework.org/schema/aop"
	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://www.springframework.org/schema/aop 
                  http://www.springframework.org/schema/aop/spring-aop.xsd		
				 http://www.springframework.org/schema/tx 
				 http://www.springframework.org/schema/tx/spring-tx-3.2.xsd">

2、@Transactional 只能被应用到public方法上, 对于其它非public的方法,如果标记了@Transactional也不会报错,但方法没有事务功能.
3、用 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("注释");
}

4、@Transactional 注解可以被应用于接口定义和接口方法、类定义和类的 public 方法上。然而,请注意仅仅 @Transactional 注解的出现不足于开启事务行为,它仅仅 是一种元数据,能够被可以识别 @Transactional 注解和上述的配置适当的具有事务行为的beans所使用。上面的例子中,其实正是 tx:annotation-driven/元素的出现 开启 了事务行为。

5、Spring团队的建议是你在具体的类(或类的方法)上使用 @Transactional 注解,而不要使用在类所要实现的任何接口上。你当然可以在接口上使用 @Transactional 注解,但是这将只能当你设置了基于接口的代理时它才生效。因为注解是 不能继承 的,这就意味着如果你正在使用基于类的代理时,那么事务的设置将不能被基于类的代理所识别,而且对象也将不会被事务代理所包装(将被确认为严重的)。因 此,请接受Spring团队的建议并且在具体的类上使用 @Transactional 注解。

二、使用AOP的方式实现事务的配置

1、事务配置实例:
(1)、配置文件

<!-- 定义事务管理器 -->
	<bean id="transactionManager"
		class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<property name="dataSource" ref="dataSource" />
	</bean>
	<!-- 下面使用aop切面的方式来实现 -->
	<tx:advice id="TestAdvice" transaction-manager="transactionManager">
		<!--配置事务传播性,隔离级别以及超时回滚等问题 -->
		<tx:attributes>
			<tx:method name="save*" propagation="REQUIRED" />
			<tx:method name="del*" propagation="REQUIRED" />
			<tx:method name="update*" propagation="REQUIRED" />
			<tx:method name="add*" propagation="REQUIRED" />
			<tx:method name="*" rollback-for="Exception" />
		</tx:attributes>
	</tx:advice>
	<aop:config>
		<!--配置事务切点 -->
		<aop:pointcut id="services"
			expression="execution(* com.website.service.*.*(..))" />
		<aop:advisor pointcut-ref="services" advice-ref="TestAdvice" />
	</aop:config>

上面我们看到了,简单的配置了事务,其中tx:attributes中设置了事务的传播性,隔离级别以及那种问题能进行回滚超时等这些问题,也就是你自己按照业务需求定制一个事务来满足你的业务需求。

注意: 这里注意一下,在tx:method中配置了rollback_for 中配置的Exception 这个是运行时的异常才会回滚不然其他异常是不会回滚的!

需要注意的地方:

(1)、在spring 配置文件中引入:xmlns:aop=“http://www.springframework.org/schema/aop”
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
如:

<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	 xmlns:tx="http://www.springframework.org/schema/tx"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:aop="http://www.springframework.org/schema/aop"
	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://www.springframework.org/schema/aop 
                  http://www.springframework.org/schema/aop/spring-aop.xsd		
				 http://www.springframework.org/schema/tx 
				 http://www.springframework.org/schema/tx/spring-tx-3.2.xsd">

(2) advice(建议)的命名:由于每个模块都会有自己的Advice,所以在命名上需要作出规范,初步的构想就是模块名+Advice(只是一种命名规范)。

(3) tx:attribute标签所配置的是作为事务的方法的命名类型。

     如<tx:method name="save*" propagation="REQUIRED"/>

    其中*为通配符,即代表以save为开头的所有方法,即表示符合此命名规则的方法作为一个事务。

    propagation="REQUIRED"代表支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择。

(4) aop:pointcut标签配置参与事务的类,由于是在Service中进行数据库业务操作,配的应该是包含那些作为事务的方法的Service类。

   首先应该特别注意的是id的命名,同样由于每个模块都有自己事务切面,所以我觉得初步的命名规则因为 all+模块名+ServiceMethod。而且每个模块之间不同之处还在于以下一句:

   expression="execution(* com.test.testAda.test.model.service.*.*(..))"

   其中第一个*代表返回值,第二*代表service下子包,第三个*代表方法名,“(..)”代表方法参数。

(5) aop:advisor标签就是把上面我们所配置的事务管理两部分属性整合起来作为整个事务管理。

下面来看看aop 这种方式来配置的时候我们还能配置那些属性:

<tx:advice id="advice" transaction-manager="txManager">
  <tx:attributes>
    <!-- tx:method的属性:
          * name 是必须的,表示与事务属性关联的方法名(业务方法名),对切入点进行细化。通配符(*)可以用来指定一批关联到相同的事务属性的方法。
                    如:'get*'、'handle*'、'on*Event'等等.
          * propagation  不是必须的 ,默认值是REQUIRED 
                            表示事务传播行为, 包括REQUIRED,SUPPORTS,MANDATORY,REQUIRES_NEW,NOT_SUPPORTED,NEVER,NESTED
          * isolation    不是必须的 默认值DEFAULT 
                            表示事务隔离级别(数据库的隔离级别) 
          * timeout      不是必须的 默认值-1(永不超时)
                            表示事务超时的时间(以秒为单位) 
          
          * read-only    不是必须的 默认值false不是只读的 
                            表示事务是否只读? 
          
          * rollback-for 不是必须的   
                            表示将被触发进行回滚的 Exception(s);以逗号分开。
                            如:'com.foo.MyBusinessException,ServletException' 
          
          * no-rollback-for 不是必须的  
                              表示不被触发进行回滚的 Exception(s);以逗号分开。
                              如:'com.foo.MyBusinessException,ServletException'
                              
                              
        任何 RuntimeException 将触发事务回滚,但是任何 checked Exception 将不触发事务回滚                      
     -->
     <tx:method name="save*" propagation="REQUIRED" isolation="DEFAULT" read-only="false"/>
     <tx:method name="update*" propagation="REQUIRED" isolation="DEFAULT" read-only="false"/>
     <tx:method name="delete*" propagation="REQUIRED" isolation="DEFAULT" read-only="false"/>
     <!-- 其他的方法之只读的 -->
     <tx:method name="*" read-only="true"/>
  </tx:attributes>
</tx:advice>

下面给大家列出spring事务的几种传播特性:

1. PROPAGATION_REQUIRED: 如果存在一个事务,则支持当前事务。如果没有事务则开启
2. PROPAGATION_SUPPORTS: 如果存在一个事务,支持当前事务。如果没有事务,则非事务的执行
3. PROPAGATION_MANDATORY: 如果已经存在一个事务,支持当前事务。如果没有一个活动的事务,则抛出异常。
4. PROPAGATION_REQUIRES_NEW: 总是开启一个新的事务。如果一个事务已经存在,则将这个存在的事务挂起。
5. PROPAGATION_NOT_SUPPORTED: 总是非事务地执行,并挂起任何存在的事务。
6. PROPAGATION_NEVER: 总是非事务地执行,如果存在一个活动事务,则抛出异常
7. PROPAGATION_NESTED:如果一个活动的事务存在,则运行在一个嵌套的事务中. 如果没有活动事务, 
      则按TransactionDefinition.PROPAGATION_REQUIRED 属性执行

Spring事务的隔离级别

1. ISOLATION_DEFAULT: 这是一个PlatfromTransactionManager默认的隔离级别,使用数据库默认的事务隔离级别,另外四个与JDBC的隔离级别相对应
2. ISOLATION_READ_UNCOMMITTED: 这是事务最低的隔离级别,它充许令外一个事务可以看到这个事务未提交的数据,这种隔离级别会产生脏读,不可重复读和幻像读。
3. ISOLATION_READ_COMMITTED:  保证一个事务修改的数据提交后才能被另外一个事务读取。另外一个事务不能读取该事务未提交的数据
4. ISOLATION_REPEATABLE_READ: 这种事务隔离级别可以防止脏读,不可重复读。但是可能出现幻像读,它除了保证一个事务不能读取另一个事务未提交的数据外,还保证了避免下面的情况产生(不可重复读)。
5. ISOLATION_SERIALIZABLE: 这是花费最高代价但是最可靠的事务隔离级别。事务被处理为顺序执行,除了防止脏读,不可重复读外,还避免了幻像读。 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值