Spring事务

Spring事务概念

事务的四大特性(ACID

原子性(Atomicity)

​ 共⽣死,要么全部成功,要么全部失败!

⼀致性(Consistency)

​ 事务在执⾏前后,数据库中数据要保持⼀致性状态。(如转账的过程 账户操作后数据必须保持⼀致)

隔离性(Isolation)

​ 事务与事务之间的执⾏应当是相互隔离互不影响的。(多个⻆色对统⼀记录进行操作必须保证没有任何干扰),当然没有影响是不可能的,为了让影响级别降到最低,通过隔离级别加以限制:

  1. READ_UNCOMMITTED (读未提交)

    隔离级别最低的⼀种事务级别。在这种隔离级别下,会引发脏读、不可重复读和幻读。

  2. READ_COMMITTED (读已提交)

    读到的都是别⼈提交后的值。这种隔离级别下,会引发不可重复读和幻读,但避免了脏读。

  3. REPEATABLE_READ (可重复读)

    ​ 这种隔离级别下,会引发幻读,但避免了脏读、不可重复读。

  4. SERIALIZABLE (串行化)

    最严格的隔离级别。在Serializable隔离级别下,所有事务按照次序依次执行。脏读、不可重复读、幻读都不会出现。

持久性(Durability)

​ 事务提交完毕后,数据库中的数据的改变是永久的。

Spring 事务核心接口

​ Spring 事务管理的实现有许多细节,如果对整个接口框架有个⼤体了解会⾮常有利于我们理解事务,下⾯通过讲解 Spring 的事务接⼝来了解 Spring 实现事务的具体策略。

在这里插入图片描述

​ Spring 并不直接管理事务,⽽是提供了多种事务管理器,他们将事务管理的职责委托给 Hibernate或者 JTA 等持久化机制所提供的相关平台框架的事务来实现。

Spring 事务管理器的接口是org.springframework.transaction.PlatformTransactionManager,通过这个接口,Spring 为各个平台如 JDBC、Hibernate 等都提供了对应的事务管理器,但是具体的实现就是各个平台自己的事情了。此接⼝的内容如下:

public interface PlatformTransactionManager(){
 // 由 TransactionDefinition 得到 TransactionStatus 对象
 TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException;
 // 提交
 void commit(TransactionStatus status) throws TransactionException;
 // 回滚
 void rollback(TransactionStatus status) throws TransactionException; }

​ 从这⾥可知具体的具体的事务管理机制对 Spring 来说是透明的,它并不关心那些,那些是对应各个平台需要关心的,所以 Spring 事务管理的⼀个优点就是为不同的事务 API 提供⼀致的编程模型,如 JTA、JDBC、Hibernate、JPA。下⾯分别介绍各个平台框架实现事务管理的机制。

JDBC 事务

​ 如果应⽤程序中直接使⽤ JDBC 来进⾏持久化,此时使用DataSourceTransactionManager 来处理事务边界。为了使用DataSourceTransactionManager,需要使⽤如下的 XML 将其装配到应⽤程序的上下文定义中:

<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
 	<property name="dataSource" ref="dataSource" />
</bea

​ 实际上,DataSourceTransactionManager 是通过调用 java.sql.Connection 来管理事务,而后者是通过 DataSource 获取到的。通过调⽤连接的 commit() ⽅法来提交事务,同样,事务失败则通过调用rollback() ⽅法进行回滚。

Hibernate 事务

​ 如果应⽤程序的持久化是通过 Hibernate 实现的,那么你需要使用HibernateTransactionManager。对于 Hibernate3,需要在 Spring 上下文定义中添加如下的声明:

<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
 <property name="sessionFactory" ref="sessionFactory" />
</bean>

​ sessionFactory 属性需要装配⼀个 Hibernate 的 session ⼯⼚,HibernateTransactionManager 的实现细节是它将事务管理的职责委托给 org.hibernate.Transaction 对象,⽽后者是从 Hibernate Session 中获取到的。当事务成功完成时,HibernateTransactionManager 将会调用Transaction 对象的 commit() ⽅法,反之,将会调⽤ rollback() ⽅法。

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 合作来构建事务。

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事务控制配置

通过 jdbc 持久化事务,对于事务配置实现由两种⽅式即:Xml 配置,注解配置。

XML 配置

添加命名空间

​ 在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

配置如下

<?xml version="1.0" encoding="UTF-8"?>
<beans 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:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.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.xsd">
设置aop代理
<!-- 开启AOP代理 -->
<aop:aspectj-autoproxy />
配置事务管理器
<!-- 事务管理器定义 -->
<bean id="txManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
 	<!--数据源 -->
 	<property name="dataSource" ref="dataSource"></property>
</bean>
配置事务相关通知

​ ⼀般来说增删改⽅法 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 将触发事务回滚
 -->
 <!--对以add update delete query开头的所有⽅法进⾏事务处理-->
<tx:advice id="txAdvice" transaction-manager="txManager">
 	<tx:attributes>
 	<!--定义什么⽅法需要使⽤事务 name代表的是⽅法名(或⽅法匹配)-->
 	<!-- 匹配以 add 开头的所有⽅法均加⼊事务 -->
 		<tx:method name="add*" 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>
事务传播⾏为介绍:
 	@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) 
 		支持当前事务,如果当前事务存在,则执行一个嵌套事务,如果当前没有事务,就新建一个事务。
配置aop
<!-- aop 切⾯定义 (切⼊点和通知) -->
<aop:config>
 <!-- 设置切⼊点 设置需要被拦截的⽅法 -->
 <aop:pointcut expression="execution(* com.xxxx.service..*.*(..) )" id="cut"/>
 <!-- 设置通知 事务通知 -->
 <aop:advisor advice-ref="txAdvice" pointcut-ref="cut"/>
<aop:adviso

注解配置

配置事务管理器
<!-- spring 注解式事务声明 -->
<!-- 事务管理器定义 -->
<bean id="txManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
 	<property name="dataSource" ref="dataSource"></property>
</bean>
配置注解支持
<tx:annotation-driven transaction-manager="txManager"/>
方法上加入事务注解

Service ⽅法上在需要添加事务的⽅法上加⼊事务注解

@Override
@Transactional(propagation=Propagation.REQUIRED)
public void saveUser(String userName,String userPwd){
 	User user1=new User();
 	user1.setUserName(userName);
 	user1.setUserPwd(userPwd);
 	userDao.saveUser(user1);
 	userDao.delUserById(2);
}

备注:默认 spring 事务只在发⽣未被捕获的 runtimeexcetpion 时才回滚。

spring aop 异常捕获原理:

IRED)
public void saveUser(String userName,String userPwd){
User user1=new User();
user1.setUserName(userName);
user1.setUserPwd(userPwd);
userDao.saveUser(user1);
userDao.delUserById(2);
}


备注:默认 **spring** 事务只在发⽣未被捕获的 **runtimeexcetpion** 时才回滚。

**spring aop** 异常捕获原理:

​		被拦截的⽅法需显式抛出异常,并不能经任何处理,这样**aop** 代理才能捕获到⽅法的异常,才能进⾏回滚,默认情况下 **aop** 只捕获 **runtimeexception** 的异常,但可以通过配置来捕获特定的异常并回滚换句话说在 **service** 的⽅法中不使⽤ **try catch** 或者在 **catch** 中最后加上 **throw new RunTimeexcetpion()**,这样程序异常时才能被 **aop 捕获进⽽回滚**.
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值