Spring之事务管理

Spring事务管理

1. 事务的定义

事务是一组不可分割的逻辑操作单元,这些操作要么全部成功执行,要么在遇到错误时全部回滚,以保持数据的一致性和完整性。

2. 四大特性(ACID)

原子性(Atomicity):事务是最小的执行单位,不可再分,事务中的所有操作要么全部完成,要么全部不执行。
一致性(Consistency):事务执行前后,数据库的状态必须保持一致。即从一个一致性状态转换到另一个一致性状态。
隔离性(Isolation):多个事务并发执行时,一个事务的执行不应被其他事务所干扰,事务之间应该相互隔离。
持久性(Durability):一旦事务被提交,它对数据库的修改就是永久性的,即使系统发生故障也不会丢失。

3. 事务引发的问题

事务在并发执行时,可能会遇到以下读问题:

脏读(Dirty Read):一个事务读取了另一个事务未提交的数据。
不可重复读(Non-repeatable Read):在同一事务内,多次读取同一数据集合时,由于其他事务的更新操作,导致每次读取的数据不一致。
幻读(Phantom Read):在同一事务内,多次读取同一范围的数据时,由于其他事务的插入操作,导致每次读取的数据行数不一致。

4. 事务的隔离级别(Isolation Levels)

数据库系统提供了几种不同的事务隔离级别,以解决上述读问题:

READ UNCOMMITTED(未提交读):最低级别,允许读取尚未提交的数据变更,可能导致脏读、不可重复读和幻读。
READ COMMITTED(已提交读):允许读取已经提交的数据,避免了脏读,但可能出现不可重复读和幻读。
REPEATABLE READ(可重复读):保证在同一个事务中多次读取同样记录的结果是一致的,避免了脏读和不可重复读,但可能出现幻读(MySQL的默认隔离级别)。
SERIALIZABLE(串行化):最高的隔离级别,通过强制事务串行执行,避免了脏读、不可重复读和幻读,但会大大降低数据库系统的并发性能。

5. Spring事务管理的原理

Spring通过PlatformTransactionManager接口提供平台无关的事务管理功能,该接口定义了事务管理的基本方法。不同的持久化技术(如JDBC、Hibernate)有不同的实现类,如JdbcTransactionManager和HibernateTransactionManager。

TransactionDefinition:定义了事务的属性,如传播行为、隔离级别、超时时间等。
TransactionStatus:表示事务的状态,如是否有保存点、是否为新事务、是否已完成等。
Spring事务管理的核心在于,当执行事务性方法时,Spring会利用PlatformTransactionManager创建事务,并根据TransactionDefinition中的定义来配置事务的属性。事务执行过程中,TransactionStatus会记录事务的状态变化,以便在需要时进行回滚或提交。

6. 事务的传播行为(Propagation Behaviors)

Spring定义了七种事务传播行为,用于控制事务的边界和嵌套关系:

PROPAGATION_REQUIRED:如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务。这是Spring的默认传播行为。
PROPAGATION_SUPPORTS:如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务方式执行。
PROPAGATION_MANDATORY:如果当前存在事务,则加入该事务;如果当前没有事务,则抛出异常。
PROPAGATION_REQUIRES_NEW:创建一个新的事务,并挂起当前事务(如果存在)。
PROPAGATION_NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,则把当前事务挂起。
PROPAGATION_NEVER:以非事务方式执行,如果当前存在事务,则抛出异常。
PROPAGATION_NESTED:如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则行为等同于PROPAGATION_REQUIRED。嵌套事务允许你有一个事务内嵌另一个事务,内层事务拥有多次的提交/回滚操作,而外层事务不受影响,只有在外层事务提交时,内层事务所做的更改才会被永久保存。
这些传播行为为开发者提供了灵活的事务控制手段,以适应不同的业务场景需求。

7. 编程式事务管理

  • 平台事务管理器

根据dao层的底层技术来选择对应的平台事务管理器

 <!-- 
 平台事务管理器
 
  -->
 <bean id="transactionManager" class="org.springframework.jdbc.support.JdbcTransactionManager">
 	<property name="dataSource" ref="dataSource"></property>
 </bean>
  • TrasactionTemplate

事务管理模板

 <!-- 
 提供了事务管理的相关操作
 采用了数据库默认的隔离级别
 采用了spring默认的传播行为  Propagtion_required
  -->
 <bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate">
 	<property name="transactionManager" ref="transactionManager"></property>
 </bean>
@Autowired
	private AccountDao dao;
	@Autowired
	private TransactionTemplate transactionTemplate; // 事务管理模板
	
	@Override
	public boolean transfer(Integer fromId, Integer toId, Integer account) {
		Boolean status = transactionTemplate.execute(new TransactionCallback<Boolean>(){
			/**
			 * 在该方法中执行的所有操作使用了同一个事务
			 */
			@Override
			public Boolean doInTransaction(TransactionStatus status) {
				int flag =0;
				flag+=dao.saveAccount(fromId, account*-1, getNow());
				sendMessage(fromId);
				flag+=dao.saveAccount(toId, account, getNow());
				sendMessage(toId);
				return flag==2?true:false;
			}
			
		});
		return status;
		
	}

缺点

改变了业务逻辑的结构

8. 声明式事务管理

在spring中提供了事务管理,采用AOP的形式,对切入点进行事务的增强,并且spring提供了事务增强的标签,只需要通过配置就能够实现事务管理。

  • 基于xml

1.平台事务管理器

2.增加tx标签,spring提供的增强

3.aop配置

<!-- 
 平台事务管理器
 
  -->
 <bean id="transactionManager" class="org.springframework.jdbc.support.JdbcTransactionManager">
 	<property name="dataSource" ref="dataSource"></property>
 </bean>
 <!-- 
 事务的增强
 transaction-manager:指定增强采用的平台事务管理器
  -->
 <tx:advice id="tx" transaction-manager="transactionManager">
 	<!-- 
 	事务的属性的配置
 	 -->
 	<tx:attributes>
 	<!-- 
 	在切入点的基础上对不同的方法进行不同的事务配置
 	 -->
 		<tx:method name="insert*" isolation="DEFAULT" propagation="REQUIRED"/>
 		<tx:method name="save*" isolation="DEFAULT" propagation="REQUIRED"/>
 		<tx:method name="update*" isolation="DEFAULT" propagation="REQUIRED"/>
 		<tx:method name="delete*" isolation="DEFAULT" propagation="REQUIRED"/>
 		<tx:method name="remove*" isolation="DEFAULT" propagation="REQUIRED"/>
 		<!-- 
 		read-only:true可以提高查询效率
 		 -->
 		<tx:method name="query*" read-only="true" isolation="DEFAULT" propagation="REQUIRED"/>
 		<tx:method name="select*" read-only="true" isolation="DEFAULT" propagation="REQUIRED"/>
 		<tx:method name="transfer" propagation="REQUIRED"/>
 	</tx:attributes>
 </tx:advice>
 <aop:config>
 	<aop:pointcut expression="execution(* com.xxx.service.impl.*.*(..))" id="p1"/>
 	<aop:advisor advice-ref="tx" pointcut-ref="p1"/>
 </aop:config>

注意

因为spring声明式事务采用的是AOP,

1.所以同类中的方法调用会导致事务失效

class Service1{
    @autoWird
    Service1 service;
	a(){
	
	}
	b(){
	
	}
	c(){
		service.a()
		int i=1/0;
		service.b()
	}
}
Service1Proxy对象调用
c() 调用的是目标对象的方法
  1. public修饰符
  2. final修饰符
  • 基于注解
  1. 定义平台事务管理器
  2. 定义事务的注解驱动
 <!-- 开启事务管理的注解驱动 
 transaction-manager:平台事务管理器
 proxy-target-class: 是否强制使用cglib
 -->
 <tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true"/>

@Transactional

类级别:该类中所有方法使用了定义的事务

方法级别:该方法使用了定义的事务

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值