1. Spring事务
-
四大特性(ACID)
原子性(Atomicity):要么全部成功,要么全部失败。 一致性(Consistency):事务在执行前后,数据库中数据要保持一致性状态。 隔离性(Isolation):事务与事务之间的执行应当是相互隔离互不影响的。 没有影响是不可能的,为了让影响级别降到最低,通过隔离级别加以限制: 1.READ_UNCOMMITTED (读未提交) 隔离级别最低的一种事务级别。在这种隔离级别下,会引发脏读、不可重复读和幻读。 2.READ_COMMITTED (读已提交) 读到的都是别人提交后的值。这种隔离级别下,会引发不可重复读和幻读,但避免了脏读。 3.REPEATABLE_READ (可重复读) 这种隔离级别下,会引发幻读,但避免了脏读、不可重复读。 4.SERIALIZABLE (串行化) 最严格的隔离级别。在Serializable隔离级别下,所有事务按照次序依次执行。脏读、不可重复读、幻读都不会出现。 持久性(Durability):事务提交完毕后,数据库中的数据的改变是永久的。
-
控制配置
1.XML配置 1.在spring.xml配置文件的添加事务和aop的命名空间 事务: xmlns:tx="http://www.springframework.org/schema/tx" http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd aop: xmlns:aop="http://www.springframework.org/schema/aop" http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd 2.设置aop代理 <!-- 开启AOP代理 --> <aop:aspectj-autoproxy /> 3.配置事务管理器 <!-- 事务管理器定义 --> <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <!--数据源 --> <property name="dataSource" ref="dataSource"></property> </bean> 4.配置事务相关通知 增删改方法propagation=Required,对于查询方法使用read-only="true" <!-- 配置事务通知 transaction-manager属性表示这个事务通知是哪个事务管理器管理的--> <!--tx:method的属性: name 是必须的,表示与事务属性关联的方法名(业务方法名),对切入点进行细化。 通配符(*)可以用来指定一批关联到相同的事务属性的方法。 如:'get*'、'handle*'、'on*Event'等等. propagation 不是必须的,默认值是REQUIRED 表示事务传播行为, 包括: REQUIRED,SUPPORTS,MANDATORY,NEVER REQUIRES_NEW,NOT_SUPPORTED,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 将触发事务回滚 --> <tx:advice id="txAdvice" transaction-manager="txManager"> <!--对以add update delete query开头的所有方法进行事务处理--> <tx:attributes> <!--定义什么方法需要使用事务 name代表的是方法名(或方法匹配)--> <!-- 匹配以 add 开头的所有方法均加入事务 --> <tx:method name="insert*" propagation="REQUIRED" /> <!-- 匹配以 update 开头的所有方法均加入事务 --> <tx:method name="update*" propagation="REQUIRED" /> <!-- 匹配以 delete 开头的所有方法均加入事务 --> <tx:method name="delete*" propagation="REQUIRED" /> <!-- 匹配以 query 开头的所有方法均加入事务 --> <tx:method name="query*" read-only="true" /> </tx:attributes> </tx:advice> 5.配置aop <!-- aop 切面定义 (切入点和通知) --> <aop:config> <!-- 设置切入点 设置需要被拦截的方法 --> <aop:pointcut expression="execution(* com.yjxxt.service..*.*(..) )" id="cut" /> <!-- 设置通知 事务通知 --> <aop:advisor advice-ref="txAdvice" pointcut-ref="cut"/> </aop:config> 2.注解配置 1.配置事务管理器 <!-- spring 注解式事务声明 --> <!-- 事务管理器定义 --> <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"></property> </bean> 2.配置注解支持 <tx:annotation-driven transaction-manager="txManager"/> 3.方法上加入事务注解 @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(propagation=Propagation.NESTED) 支持当前事务,如果当前事务存在,则执行一个嵌套事务,如果当前没有事务,就新建一个事务。 注意:默认spring事务只在发生未被捕获的runtimeexcetpion时才回滚。 spring aop异常捕获原理: 被拦截的方法需显式抛出异常,并不能经任何处理,这样aop代理才能捕获到方法的异常,才能进行回滚, 默认情况下aop只捕获runtimeexception的异常,但可以通过配置来捕获特定的异常并回滚, 换句话说在service的方法中不使用try catch或者在catch中最后加上 throw new RunTimeexcetpion(),这样程序异常时才能被aop捕获进而回滚。