Spring事务管理
本文对Spring事务管理做简单讲解,在学习本文之前请先了解数据库隔离级别与事务的概念。
在学习之前先了解Spring隔离级别,Spring事务传播。
一、Spring隔离级别
① ISOLATION_DEFAULT:这是一个PlatfromTransactionManager默认的隔离级别,使用数据库默认的事务隔离级别。另外四个与JDBC的隔离级别相对应
② ISOLATION_READ_UNCOMMITTED:这是事务最低的隔离级别,它充许另外一个事务可以看到这个事务未提交的数据。这种隔离级别会产生脏读,不可重复读和幻读。
③ ISOLATION_READ_COMMITTED:保证一个事务修改的数据提交后才能被另外一个事务读取。另外一个事务不能读取该事务未提交的数据。
④ ISOLATION_REPEATABLE_READ:这种事务隔离级别可以防止脏读,不可重复读。但是可能出现幻读。
⑤ ISOLATION_SERIALIZABLE:这是花费最高代价但是最可靠的事务隔离级别。事务被处理为顺序执行。除了防止脏读,不可重复读外,还避免了幻读。
二、Spring事务传播性
① PROPAGATION_REQUIRED:支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择,也是Spring默认的事务的传播。
② PROPAGATION_SUPPORTS:支持当前事务,如果当前没有事务,就以非事务方式执行。
③ PROPAGATION_MANDATORY:支持当前事务,如果当前没有事务,就抛出异常。
④ PROPAGATION_REQUIRES_NEW:新建事务,如果当前存在事务,把当前事务挂起。
⑤ PROPAGATION_NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
⑥ PROPAGATION_NEVER:以非事务方式执行,如果当前存在事务,则抛出异常。
⑦ PROPAGATION_NESTED:如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则进行与PROPAGATION_REQUIRED类似的操作。
三、核心接口
四、事务管理器
Spring并不直接管理事务,而是提供了多种事务管理器,他们将事务管理的职责委托给Hibernate或者JTA等持久化机制所提供的相关平台框架的事务来实现。
Spring事务管理器的接口是org.springframework.transaction.PlatformTransactionManager,通过这个接口,Spring为各个平台如JDBC、Hibernate等都提供了对应的事务管理器,但是具体的实现就是各个平台自己的事情了。此接口的内容如下:
package org.springframework.transaction;
public interface PlatformTransactionManager {
TransactionStatus getTransaction(TransactionDefinition var1) throws TransactionException;
void commit(TransactionStatus var1) throws TransactionException;
void rollback(TransactionStatus var1) throws TransactionException;
}
1.JDBC事务
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource" /> </bean>
2.Hibernete事务
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"> <property name="sessionFactory" ref="sessionFactory" /> </bean>
3.Java持久化API事务(JPA)
Hibernate多年来一直是事实上的Java持久化标准,但是现在Java持久化API作为真正的Java持久化标准进入大家的视野。如果你计划使用JPA的话,那你需要使用Spring的JpaTransactionManager来处理事务。你需要在Spring中这样配置JpaTransactionManager:
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"> <property name="sessionFactory" ref="sessionFactory" /> </bean>
JpaTransactionManager只需要装配一个JPA实体管理工厂(javax.persistence.EntityManagerFactory接口的任意实现)。JpaTransactionManager将与由工厂所产生的JPA EntityManager合作来构建事务。
4.Java原生API事务
如果你没有使用以上所述的事务管理,或者是跨越了多个事务管理源(比如两个或者是多个不同的数据源),你就需要使用JtaTransactionManager:
<bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager"> <property name="transactionManagerName" value="java:/TransactionManager" /> </bean>
JtaTransactionManager将事务管理的责任委托给javax.transaction.UserTransaction和javax.transaction.TransactionManager对象,其中事务成功完成通过UserTransaction.commit()方法提交,事务失败通过UserTransaction.rollback()方法回滚。
五、事务管理方式配置
配置了事务管理器后,事务当然还是得我们自己去操作,Spring提供了两种事务管理的方式:编程式事务管理和声明式事务管理,让我们分别看看它们是怎么做的吧。
1. 编程式事务管理
编程式事务管理我们可以通过PlatformTransactionManager实现来进行事务管理,同样的Spring也为我们提供了模板类TransactionTemplate进行事务管理,下面主要介绍模板类,我们需要在配置文件中配置
<!--配置事务管理的模板--> <bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate"> <property name="transactionManager" ref="transactionManager"></property> <!--定义事务隔离级别,-1表示使用数据库默认级别--> <property name="isolationLevelName" value="ISOLATION_DEFAULT"></property> <property name="propagationBehaviorName" value="PROPAGATION_REQUIRED"></property> </bean>
测试代码
package com.gray;
import com.gray.service.BaseSevice;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;
import javax.annotation.Resource;
/**
* Created by gray on 2017/4/8.
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:spring-test.xml"})
public class TransactionTest{
@Resource
private TransactionTemplate transactionTemplate;
@Autowired
private BaseSevice baseSevice;
@Test
public void transTest() {
System.out.println("before transaction");
Integer sum1 = baseSevice.sum();
System.out.println("before transaction sum: "+sum1);
System.out.println("transaction....");
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus status) {
try{
baseSevice.insert("INSERT INTO tbl_account VALUES (100);",false);
baseSevice.insert("INSERT INTO tbl_account VALUES (100);",false);
} catch (Exception e){
//对于抛出Exception类型的异常且需要回滚时,需要捕获异常并通过调用status对象的setRollbackOnly()方法告知事务管理器当前事务需要回滚
status.setRollbackOnly();
e.printStackTrace();
}
}
});
System.out.println("after transaction");
Integer sum2 = baseSevice.sum();
System.out.println("after transaction sum: "+sum2);
}
}
2. 声明式事务管理
声明式事务管理有两种常用的方式,一种是基于tx和aop命名空间的xml配置文件,一种是基于@Transactional注解,随着Spring和Java的版本越来越高,大家越趋向于使用注解的方式,下面我们两个都说。
1.基于tx和aop命名空间的xml配置文件
配置文件
<tx:advice id="advice" transaction-manager="transactionManager"> <tx:attributes> <tx:method name="insert" propagation="REQUIRED" read-only="false" rollback-for="Exception"/> </tx:attributes> </tx:advice> <aop:config> <aop:pointcut id="pointCut" expression="execution (* com.gray.service.*.*(..))"/> <aop:advisor advice-ref="advice" pointcut-ref="pointCut"/> </aop:config>
3. 基于@Transactional注解
这种方式最简单,也是最为常用的,只需要在配置文件中开启对注解事务管理的支持。
<!-- 声明式事务管理 配置事物的注解方式注入--> <tx:annotation-driven transaction-manager="transactionManager"/>
然后在需要事务管理的地方加上@Transactional注解,如:
@Transactional(rollbackFor=Exception.class)
public void insert(String sql, boolean flag) throws Exception {
dao.insertSql(sql);
// 如果flag 为 true ,抛出异常
if (flag){
throw new Exception("has exception!!!");
}
}
查看原文:http://www.coder306.cn/?p=113