ToB企服应用市场:ToB评测及商务社交产业平台

标题: Spring 事务相关Java [打印本页]

作者: 刘俊凯    时间: 2024-12-13 00:19
标题: Spring 事务相关Java
深入明白 Spring 事务

一、引言

在企业级应用开发中,事务管理是确保数据同等性和完备性的关键环节。Spring 框架提供了强盛而机动的事务管理功能,使得开发者可以或许方便地在各种应用场景中处理事务。本文将深入探究 Spring 事务的原理、特性、使用方式,并通过详细的示例代码帮助读者更好地明白和应用 Spring 事务。
二、事务的根本概念

事务是一组逻辑操作单元,这些操作要么全部乐成执行,要么全部失败回滚,以保证数据的同等性。例如,在一个银行转账体系中,从一个账户扣款并向另一个账户收款的操作必须作为一个事务来处理。假如扣款乐成但收款失败,那么整个事务应该回滚,以确保两个账户的余额数据始终保持精确的状态。
三、Spring 事务的特性

(一)原子性(Atomicity)

原子性确保事务中的所有操作要么全部完成,要么全部不完成。就像一个不可分割的原子,事务中的任何一个操作失败,都会导致整个事务回滚到初始状态,就好像该事务从未发生过一样。
(二)同等性(Consistency)

事务在开始和竣事时,数据都必须处于同等的状态。例如,在数据库事务中,遵循特定的约束规则(如主键唯一性、外键约束等),事务执行前后数据都应符合这些规则。
(三)隔离性(Isolation)

多个事务并发执行时,每个事务都应该感觉不到其他事务的存在,它们之间相互隔离。不同的隔离级别可以控制事务之间的可见性和相互影响程度,例如,一个事务不能读取到其他事务未提交的数据(未提交读隔离级别除外)。
(四)长期性(Durability)

一旦事务乐成提交,其所做的修改就应该永世保存到数据库或其他长期化存储中,即使体系出现故障也不应丢失。
四、Spring 事务的实现方式

(一)编程式事务管理

编程式事务管理允许开发者在代码中显式地控制事务的开始、提交和回滚。这种方式提供了最大程度的机动性,但也使得代码与事务管理逻辑细密耦合。
以下是一个使用编程式事务管理的示例:
  1. import org.springframework.transaction.PlatformTransactionManager;
  2. import org.springframework.transaction.TransactionDefinition;
  3. import org.springframework.transaction.TransactionStatus;
  4. import org.springframework.transaction.support.DefaultTransactionDefinition;
  5. public class TransactionExample {
  6.     private final PlatformTransactionManager transactionManager;
  7.     public TransactionExample(PlatformTransactionManager transactionManager) {
  8.         this.transactionManager = transactionManager;
  9.     }
  10.     public void doTransaction() {
  11.         // 定义事务属性
  12.         TransactionDefinition def = new DefaultTransactionDefinition();
  13.         // 获取事务状态
  14.         TransactionStatus status = transactionManager.getTransaction(def);
  15.         try {
  16.             // 执行业务逻辑操作,这里假设是数据库操作
  17.             //...
  18.             // 提交事务
  19.             transactionManager.commit(status);
  20.         } catch (Exception e) {
  21.             // 回滚事务
  22.             transactionManager.rollback(status);
  23.             e.printStackTrace();
  24.         }
  25.     }
  26. }
复制代码
在上述示例中,起首创建了一个TransactionDefinition对象来定义事务的属性,如事务的隔离级别、流传行为等。然后通过PlatformTransactionManager获取TransactionStatus,并在try-catch块中执行业务逻辑。假如业务逻辑执行乐成,则提交事务;假如出现非常,则回滚事务。
(二)声明式事务管理

声明式事务管理是 Spring 事务管理的主要方式,它通过在设置文件(XML 或 Java 设置)或使用注解来声明事务的界限,将事务管理与业务逻辑分离,使得代码更加简洁、可维护性更高。
  1. <?xml version="10.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3.        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4.        xmlns:tx="http://www.springframework.org/schema/tx"
  5.        xsi:schemaLocation="
  6.         http://www.springframework.org/schema/beans
  7.         http://www.springframework.org/schema/beans/spring-beans.xsd
  8.         http://www.springframework.org/schema/tx
  9.         http://www.springframework.org/schema/tx/spring-tx.xsd">
  10.     <!-- 配置事务管理器 -->
  11.     <bean id="transactionManager" class="org.springframework.jdbc.driver.DataSourceTransactionManager">
  12.         <property name="dataSource" ref="dataSource"/>
  13.     </bean>
  14.     <!-- 开启事务注解驱动 -->
  15.     <tx:annotation-driven transaction-manager="transactionManager"/>
  16.     <!-- 定义事务代理 -->
  17.     <tx:advice id="txAdvice" transaction-manager="transactionManager">
  18.         <tx:attributes>
  19.             <!-- 对指定方法设置事务属性 -->
  20.             <tx:method name="transfer" propagation="REQUIRED"/>
  21.             <tx:method name="*" read-only="true"/>
  22.         </tx:attributes>
  23.     </tx:advice>
  24.     <!-- 配置事务代理的切入点 -->
  25.     <aop:config>
  26.         <aop:pointcut id="serviceOperation" expression="execution(* com.example.service.*.*(..))"/>
  27.         <aop:advisor advice-ref="txAdvice" pointcut-ref="serviceOperation"/>
  28.     </aop:config>
  29. </beans>
复制代码
在这个 XML 设置中,起首设置了一个DataSourceTransactionManager作为事务管理器,并通过<tx:annotation-driven>开启了事务注解驱动。然后使用<tx:advice>定义了事务的属性,如对于transfer方法设置了REQUIRED的流传行为,对于其他方法设置为只读事务。最后通过<aop:config>设置了事务代理的切入点,将事务应用到com.example.service包下的所有方法。
  1. import org.springframework.transaction.annotation.Transactional;
  2. @Transactional
  3. public class BankService {
  4.     public void transfer(String fromAccount, String toAccount, double amount) {
  5.         // 实现转账逻辑,这里涉及数据库操作
  6.         //...
  7.     }
  8. }
复制代码
在上述示例中,使用@Transactional注解标记了BankService类的transfer方法,该方法将在事务环境中执行。假如transfer方法执行过程中出现非常,事务将自动回滚。
五、Spring 事务的流传行为

事务流传行为定义了在一个事务方法被另一个事务方法调用时,事务应该怎样流传。Spring 提供了多种流传行为,常用的有以下几种:
(一)REQUIRED(默认)

假如当前存在事务,则参加该事务;假如当前没有事务,则创建一个新事务。例如:
  1. @Transactional(propagation = Propagation.REQUIRED)
  2. public void methodA() {
  3.     // 业务逻辑操作
  4.     methodB();
  5. }
  6. @Transactional(propagation = Propagation.REQUIRED)
  7. public void methodB() {
  8.     // 业务逻辑操作
  9. }
复制代码
当methodA被调用时,假如当前没有事务,则创建一个新事务,然后在methodA中调用methodB时,methodB会参加到methodA创建的事务中。
(二)REQUIRES_NEW

总是创建一个新事务,假如当前存在事务,则将当前事务挂起。例如:
  1. @Transactional(propagation = Propagation.REQUIRED)
  2. public void methodA() {
  3.     // 业务逻辑操作
  4.     methodB();
  5. }
  6. @Transactional(propagation = Propagation.REQUIRES_NEW)
  7. public void methodB() {
  8.     // 业务逻辑操作
  9. }
复制代码
当methodA被调用时,假如当前没有事务,则创建一个新事务,在methodA中调用methodB时,methodB会创建一个新的独立事务,并且methodA的事务会被挂起,直到methodB的新事务完成。
(三)SUPPORTS

假如当前存在事务,则参加该事务;假如当前没有事务,则以非事务方式执行。例如:
  1. @Transactional(propagation = Propagation.REQUIRED)
  2. public void methodA() {
  3.     // 业务逻辑操作
  4.     methodB();
  5. }
  6. @Transactional(propagation = Propagation.SUPPORTS)
  7. public void methodB() {
  8.     // 业务逻辑操作
  9. }
复制代码
当methodA被调用且存在事务时,methodB会参加到methodA的事务中;假如methodA没有事务,则methodB以非事务方式执行。
(四)NOT_SUPPORTED

总是以非事务方式执行,假如当前存在事务,则将当前事务挂起。例如:
  1. @Transactional(propagation = Propagation.REQUIRED)
  2. public void methodA() {
  3.     // 业务逻辑操作
  4.     methodB();
  5. }
  6. @Transactional(propagation = Propagation.NOT_SUPPORTED)
  7. public void methodB() {
  8.     // 业务逻辑操作
  9. }
复制代码
当methodA被调用且存在事务时,methodB会以非事务方式执行,并且methodA的事务会被挂起。
(五)MANDATORY

假如当前存在事务,则参加该事务;假如当前没有事务,则抛出非常。例如:
  1. @Transactional(propagation = Propagation.REQUIRED)
  2. public void methodA() {
  3.     // 业务逻辑操作
  4.     methodB();
  5. }
  6. @Transactional(propagation = Propagation.MANDATORY)
  7. public void methodB() {
  8.     // 业务逻辑操作
  9. }
复制代码
当methodA被调用且存在事务时,methodB会参加到methodA的事务中;假如methodA没有事务,则调用methodB时会抛出非常。
六、Spring 事务的隔离级别

Spring 事务支持多种隔离级别,与数据库的隔离级别相对应,包括:
(一)DEFAULT(默认)

使用数据库默认的隔离级别。不同数据库的默认隔离级别可能不同,例如 MySQL 的默认隔离级别是可重复读(REPEATABLE READ)。
(二)READ_UNCOMMITTED

允许读取未提交的数据,可能会导致脏读、不可重复读和幻读等问题。
(三)READ_COMMITTED

只能读取已提交的数据,可以制止脏读,但可能会出现不可重复读的环境。
(四)REPEATABLE_READ

在同一个事务中多次读取同一数据的结果是相同的,可以制止脏读和不可重复读,但可能会出现幻读。
(五)SERIALIZABLE

最高的隔离级别,事务串行化执行,完全制止了脏读、不可重复读和幻读,但性能开销较大。
可以在@Transactional注解或 XML 设置中设置事务的隔离级别,例如:
  1. @Transactional(isolation = Isolation.READ_COMMITTED)
  2. public void method() {
  3.     // 业务逻辑操作
  4. }
复制代码
大概在 XML 设置中:
  1. <tx:method name="method" isolation="READ_COMMITTED"/>
复制代码
七、Spring 事务的回滚规则

默认环境下,Spring 事务会在运行时抛出未查抄非常(RuntimeException 及其子类)或 Error 时回滚,而对于查抄非常(如 IOException、SQLException 等),事务不会回滚。但可以通过@Transactional注解的rollbackFor或noRollbackFor属性来指定回滚或不回滚的非常类型。
例如:
  1. @Transactional(rollbackFor = Exception.class)
  2. public void method() {
  3.     // 业务逻辑操作,如果抛出任何异常都会回滚事务
  4. }
复制代码
大概
  1. @Transactional(noRollbackFor = IOException.class)
  2. public void method() {
  3.     // 业务逻辑操作,即使抛出 IOException 异常也不会回滚事务
  4. }
复制代码
八、总结

Spring 事务管理为开发者提供了强盛而机动的方式来处理企业级应用中的事务。通过明白 Spring 事务的根本概念、特性、实现方式、流传行为、隔离级别和回滚规则,并联合实际的示例代码进行学习和实践,可以或许帮助开发者更好地在 Spring 框架下构建可靠、高效的应用程序,确保数据的同等性和完备性,提高体系的稳固性和可维护性。在实际应用中,需要根据详细的业务需求和场景,公道选择事务管理方式、流传行为、隔离级别等参数,以达到最佳的性能和效果。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。




欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/) Powered by Discuz! X3.4