首页 > 编程语言 >Spring 事务相关Java

Spring 事务相关Java

时间:2024-12-11 17:58:57浏览次数:8  
标签:事务 Java Spring Transactional methodB methodA public

深入理解 Spring 事务

一、引言

在企业级应用开发中,事务管理是确保数据一致性和完整性的关键环节。Spring 框架提供了强大而灵活的事务管理功能,使得开发者能够方便地在各种应用场景中处理事务。本文将深入探讨 Spring 事务的原理、特性、使用方式,并通过详细的示例代码帮助读者更好地理解和应用 Spring 事务。

二、事务的基本概念

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

三、Spring 事务的特性

(一)原子性(Atomicity)

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

(二)一致性(Consistency)

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

(三)隔离性(Isolation)

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

(四)持久性(Durability)

一旦事务成功提交,其所做的修改就应该永久保存到数据库或其他持久化存储中,即使系统出现故障也不应丢失。

四、Spring 事务的实现方式

(一)编程式事务管理

编程式事务管理允许开发者在代码中显式地控制事务的开始、提交和回滚。这种方式提供了最大程度的灵活性,但也使得代码与事务管理逻辑紧密耦合。

以下是一个使用编程式事务管理的示例:

import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;

public class TransactionExample {

    private final PlatformTransactionManager transactionManager;

    public TransactionExample(PlatformTransactionManager transactionManager) {
        this.transactionManager = transactionManager;
    }

    public void doTransaction() {
        // 定义事务属性
        TransactionDefinition def = new DefaultTransactionDefinition();
        // 获取事务状态
        TransactionStatus status = transactionManager.getTransaction(def);
        try {
            // 执行业务逻辑操作,这里假设是数据库操作
            //...
            // 提交事务
            transactionManager.commit(status);
        } catch (Exception e) {
            // 回滚事务
            transactionManager.rollback(status);
            e.printStackTrace();
        }
    }
}

在上述示例中,首先创建了一个TransactionDefinition对象来定义事务的属性,如事务的隔离级别、传播行为等。然后通过PlatformTransactionManager获取TransactionStatus,并在try-catch块中执行业务逻辑。如果业务逻辑执行成功,则提交事务;如果出现异常,则回滚事务。

(二)声明式事务管理

声明式事务管理是 Spring 事务管理的主要方式,它通过在配置文件(XML 或 Java 配置)或使用注解来声明事务的边界,将事务管理与业务逻辑分离,使得代码更加简洁、可维护性更高。

  1. 基于 XML 配置的声明式事务管理
<?xml version="10.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       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/tx
        http://www.springframework.org/schema/tx/spring-tx.xsd">

    <!-- 配置事务管理器 -->
    <bean id="transactionManager" class="org.springframework.jdbc.driver.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>

    <!-- 开启事务注解驱动 -->
    <tx:annotation-driven transaction-manager="transactionManager"/>

    <!-- 定义事务代理 -->
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <tx:attributes>
            <!-- 对指定方法设置事务属性 -->
            <tx:method name="transfer" propagation="REQUIRED"/>
            <tx:method name="*" read-only="true"/>
        </tx:attributes>
    </tx:advice>

    <!-- 配置事务代理的切入点 -->
    <aop:config>
        <aop:pointcut id="serviceOperation" expression="execution(* com.example.service.*.*(..))"/>
        <aop:advisor advice-ref="txAdvice" pointcut-ref="serviceOperation"/>
    </aop:config>

</beans>

在这个 XML 配置中,首先配置了一个DataSourceTransactionManager作为事务管理器,并通过<tx:annotation-driven>开启了事务注解驱动。然后使用<tx:advice>定义了事务的属性,如对于transfer方法设置了REQUIRED的传播行为,对于其他方法设置为只读事务。最后通过<aop:config>配置了事务代理的切入点,将事务应用到com.example.service包下的所有方法。

  1. 基于注解的声明式事务管理
import org.springframework.transaction.annotation.Transactional;

@Transactional
public class BankService {

    public void transfer(String fromAccount, String toAccount, double amount) {
        // 实现转账逻辑,这里涉及数据库操作
        //...
    }
}

在上述示例中,使用@Transactional注解标记了BankService类的transfer方法,该方法将在事务环境中执行。如果transfer方法执行过程中出现异常,事务将自动回滚。

五、Spring 事务的传播行为

事务传播行为定义了在一个事务方法被另一个事务方法调用时,事务应该如何传播。Spring 提供了多种传播行为,常用的有以下几种:

(一)REQUIRED(默认)

如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新事务。例如:

@Transactional(propagation = Propagation.REQUIRED)
public void methodA() {
    // 业务逻辑操作
    methodB();
}

@Transactional(propagation = Propagation.REQUIRED)
public void methodB() {
    // 业务逻辑操作
}

methodA被调用时,如果当前没有事务,则创建一个新事务,然后在methodA中调用methodB时,methodB会加入到methodA创建的事务中。

(二)REQUIRES_NEW

总是创建一个新事务,如果当前存在事务,则将当前事务挂起。例如:

@Transactional(propagation = Propagation.REQUIRED)
public void methodA() {
    // 业务逻辑操作
    methodB();
}

@Transactional(propagation = Propagation.REQUIRES_NEW)
public void methodB() {
    // 业务逻辑操作
}

methodA被调用时,如果当前没有事务,则创建一个新事务,在methodA中调用methodB时,methodB会创建一个新的独立事务,并且methodA的事务会被挂起,直到methodB的新事务完成。

(三)SUPPORTS

如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务方式执行。例如:

@Transactional(propagation = Propagation.REQUIRED)
public void methodA() {
    // 业务逻辑操作
    methodB();
}

@Transactional(propagation = Propagation.SUPPORTS)
public void methodB() {
    // 业务逻辑操作
}

methodA被调用且存在事务时,methodB会加入到methodA的事务中;如果methodA没有事务,则methodB以非事务方式执行。

(四)NOT_SUPPORTED

总是以非事务方式执行,如果当前存在事务,则将当前事务挂起。例如:

@Transactional(propagation = Propagation.REQUIRED)
public void methodA() {
    // 业务逻辑操作
    methodB();
}

@Transactional(propagation = Propagation.NOT_SUPPORTED)
public void methodB() {
    // 业务逻辑操作
}

methodA被调用且存在事务时,methodB会以非事务方式执行,并且methodA的事务会被挂起。

(五)MANDATORY

如果当前存在事务,则加入该事务;如果当前没有事务,则抛出异常。例如:

@Transactional(propagation = Propagation.REQUIRED)
public void methodA() {
    // 业务逻辑操作
    methodB();
}

@Transactional(propagation = Propagation.MANDATORY)
public void methodB() {
    // 业务逻辑操作
}

methodA被调用且存在事务时,methodB会加入到methodA的事务中;如果methodA没有事务,则调用methodB时会抛出异常。

六、Spring 事务的隔离级别

Spring 事务支持多种隔离级别,与数据库的隔离级别相对应,包括:

(一)DEFAULT(默认)

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

(二)READ_UNCOMMITTED

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

(三)READ_COMMITTED

只能读取已提交的数据,可以避免脏读,但可能会出现不可重复读的情况。

(四)REPEATABLE_READ

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

(五)SERIALIZABLE

最高的隔离级别,事务串行化执行,完全避免了脏读、不可重复读和幻读,但性能开销较大。

可以在@Transactional注解或 XML 配置中设置事务的隔离级别,例如:

@Transactional(isolation = Isolation.READ_COMMITTED)
public void method() {
    // 业务逻辑操作
}

或者在 XML 配置中:

<tx:method name="method" isolation="READ_COMMITTED"/>

七、Spring 事务的回滚规则

默认情况下,Spring 事务会在运行时抛出未检查异常(RuntimeException 及其子类)或 Error 时回滚,而对于检查异常(如 IOException、SQLException 等),事务不会回滚。但可以通过@Transactional注解的rollbackFornoRollbackFor属性来指定回滚或不回滚的异常类型。

例如:

@Transactional(rollbackFor = Exception.class)
public void method() {
    // 业务逻辑操作,如果抛出任何异常都会回滚事务
}

或者

@Transactional(noRollbackFor = IOException.class)
public void method() {
    // 业务逻辑操作,即使抛出 IOException 异常也不会回滚事务
}

八、总结

Spring 事务管理为开发者提供了强大而灵活的方式来处理企业级应用中的事务。通过理解 Spring 事务的基本概念、特性、实现方式、传播行为、隔离级别和回滚规则,并结合实际的示例代码进行学习和实践,能够帮助开发者更好地在 Spring 框架下构建可靠、高效的应用程序,确保数据的一致性和完整性,提高系统的稳定性和可维护性。在实际应用中,需要根据具体的业务需求和场景,合理选择事务管理方式、传播行为、隔离级别等参数,以达到最佳的性能和效果。

标签:事务,Java,Spring,Transactional,methodB,methodA,public
From: https://blog.csdn.net/weixin_69477306/article/details/144406836

相关文章

  • 免费送源码:Java+ssm+springboot springboot高校网上选课系统 计算机毕业设计原创定制
    摘要本论文主要论述了如何使用JAVA语言开发一个高校网上选课系统,本系统将严格按照软件开发流程进行各个阶段的工作,采用B/S架构,面向对象编程思想进行项目开发。在引言中,作者将论述高校网上选课系统的当前背景以及系统开发的目的,后续章节将严格按照软件开发流程,对系统进行......
  • 为什么 Java 中某些新生代和老年代的垃圾收集器不能组合使用?
    为什么Java中某些新生代和老年代的垃圾收集器不能组合使用?在JVM中,新生代和老年代的垃圾收集器是分工协作的。然而,并非所有的新生代和老年代垃圾收集器都能任意组合使用,这是由于它们的设计目标、算法特性和交互方式不兼容所导致的。例如,新生代的ParNew和老年代的ParallelO......
  • 什么是 Java 的 PLAB(Promotion Local Allocation Buffer)?
    什么是Java的PLAB(PromotionLocalAllocationBuffer)?PLAB全称是PromotionLocalAllocationBuffer,是Java垃圾回收机制中的一个重要概念,主要用于优化对象晋升(Promotion)的性能。PLAB是在垃圾回收器处理内存分配时,为每个线程分配的一块缓冲区域,专门用于临时存放从新生代晋......
  • JAVA中ScheduledExecutorService的使用方法
    ScheduledExecutorService简介ScheduledExecutorService是Java中的一个接口,它是ExecutorService的子接口。它主要用于在给定的延迟之后或周期性地执行任务。这个接口提供了一种方便的方式来处理异步任务的调度,相比于传统的Timer和TimerTask,它具有更好的灵活性和可靠性,特别是......
  • JavaScript 的模块化:AMD、ES Module 和 Webpack
    一、AMD(AsynchronousModuleDefinition)什么是AMD?AMD是一种为浏览器环境设计的模块定义规范。它通过异步加载模块,解决了早期前端开发中JavaScript文件依赖关系复杂的问题。require.jshttps://requirejs.org/docs/api.html#jsfiles语法示例define(['dependency1','......
  • maven仓库配置,Tomcat配置,javaweb项目创建
    把maven安装到一个没有中文目录下的文件夹中maven官网下载地址:下载地址:DownloadApacheMaven–Maven配置仓库进入maven文件夹在maven文件夹中创建仓库文件夹(注意不要中文)然后进入conf文件夹中的setting.xml文件打开,找到以下位置添加以下文件,配置阿里云私服<mirror>......
  • Java框架 —— Spring
    Spring简介 一般来说,Spring指的是SpringFramework,它提供了很多功能,例如:控制反转(IOC)、依赖注入(DI)、切面编程(AOP)、事务管理(TX)主要jar包org.springframework.core:Spring的核心工具包,其他包依赖此包org.springframework.beans:所有应用都用到,包含访问配置文件,创建和管理b......
  • 为什么前后端分离的项目中,后端代码比如java servlet中session就无法跟踪客户端
    这是由于前、后端分离架构的特性导致的。原因如下:1.传统的Web应用vs前后端分离:1.传统Web应用:服务器直接生成完整的HTML页面,session可以轻松地通过cookie来维护。2.前后端分离:前端(通常是单页应用SPA)和后端(API服务)是分开的,它们可能运行在不同的域名下。 2.Session的工作原......
  • 在SpringBoot当中使用Spring AOP来实现权限验证和消息管理
    引言1.权限验证在之前的Blog项目当中,其实已经体验过权限验证了,不过那时候用的是SpringSecurityAPI来实现的方法,当没使用API时,可以使用Spring的AOP来进行权限验证了.其实也可以通过使用拦截器来实现登录权限验证,但是AOP相对而言更加灵活消息管理2.消息管理通过Srping......
  • Java+seetaface6实现人脸识别
    seetaface6是中科视拓开源的一套基于深度学习的高性能人脸识别框架,其中包含了人脸检测、人脸识别、人脸跟踪、口罩检测、年龄估计、性别估计、特征点检测、眼睛状态检测、质量评估器、静默活体功能。seetaface6SDK是基于seetaface6源码和seetaface6JNI源码编译得到的一个sdk......