首页 > 其他分享 >Spring中如何开启事务

Spring中如何开启事务

时间:2024-06-12 21:03:53浏览次数:22  
标签:事务 default Spring Transactional 开启 注解 public

事务管理在系统开发中是不可缺少的一部分,Spring提供了很好事务管理机制,主要分为编程式事务和声明式事务两种。

声明事务

声明式事务是通过配置的方式来管理事务的行为,声明式事务的好处是可以将事务管理与业务逻辑相分离,提高了代码的可读性和维护性。

声明事务的代码很简单,我们也是经常使用的。


import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
public class UserService {

    @Transactional
    public void performTransaction() {
        // 事务逻辑
    }
}

编程事务

编程式事务是通过编写代码显式地管理事务的开始、提交和回滚。使用编程式事务可以更加灵活地控制事务的细节,但需要更多的代码来处理事务管理,可能导致代码的冗余和增加了复杂性。

编程事务,需要自己来控制事务的流程,更加灵活但也更加复杂,一般不建议使用。(实际上我也没在生产环境中用过)

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;

@Service
public class TransactionService {

    private final TransactionTemplate transactionTemplate;

    @Autowired
    public TransactionService(TransactionTemplate transactionTemplate) {
        this.transactionTemplate = transactionTemplate;
    }

    public void performTransaction() {
        transactionTemplate.execute(new TransactionCallbackWithoutResult() {
            protected void doInTransactionWithoutResult(TransactionStatus status) {
                try {
                    // 事务逻辑
                } catch (Exception e) {
                    status.setRollbackOnly();
                    throw e;
                }
            }
        });
    }
}

声明事务是怎么实现的

虽然我们实现事务的方式有声明式和编程式,但在实际的使用中,我们只会用声明式,所以我们有必要来深入理解一下声明事务。

其实简单来说在Spring中,我们开启声明事务用的是@Transactional ,本质上是使用的 代理和AOP来实现。

  1. 事务拦截器链(Interceptor Chain):Spring的声明式事务依赖于AOP技术,在运行时动态生成代理对象并创建事务拦截器链。在方法调用链中,每个事务拦截器都会被依次调用,并根据事务属性的定义决定是否开启、提交或回滚事务。

  2. 事务切点(Transaction Pointcut):事务切点定义了哪些方法需要被事务拦截器拦截并应用事务逻辑。切点通过表达式语言(如Spring表达式语言)或基于注解的方式来指定匹配的方法。Spring提供了灵活的切点表达式来满足各种粒度的事务控制需求。

  3. 事务属性解析:在声明式事务中,事务属性可以通过注解(如@Transactional)或配置文件来指定。事务属性包括隔离级别、传播行为、超时设置等。Spring会解析事务属性,并将其应用于方法上,以确定事务的行为。事务属性解析器根据事务定义的优先级,从全局配置或方法级别的注解中获取事务属性。

  4. 事务管理器(Transaction Manager):事务管理器是Spring框架的核心组件之一。它负责处理实际的事务管理操作,与底层的数据访问技术(如JDBC、Hibernate等)进行交互。事务管理器负责事务的创建、提交和回滚,并与当前线程进行绑定。Spring提供了多种事务管理器的实现,如DataSourceTransactionManagerJpaTransactionManager等,可以根据具体的数据访问技术进行配置。

  5. 事务同步器(Transaction Synchronization):事务同步器用于在事务的不同阶段注册回调方法。在事务提交或回滚时,事务同步器会触发注册的回调方法,以执行一些额外的操作。例如,清理数据库连接、提交缓存数据等。Spring利用事务同步器来确保与事务相关的资源的正确管理和释放。

  6. 事务切面(Transaction Aspect):事务切面是由事务拦截器和事务切点组成的,它定义了在目标方法执行前后应用事务逻辑的规则。事务切面通过AOP技术将事务管理逻辑与业务逻辑进行解耦。当目标方法被调用时,事务切面会根据事务属性的定义,决定是否开启、提交。

@Transactional 注解的参数

在声明事务中,我们只需要和注解 @Transactional 打交道,所以我们有必要来深入理解一下这个注解中的参数配置。

public @interface Transactional {
    @AliasFor("transactionManager")
    String value() default "";
    
    // 事务管理器、暂时先忽略它,我们也不会去修改这个参数的值
    @AliasFor("value")
    String transactionManager() default "";

    String[] label() default {};
    
    // 事务传播行为
    Propagation propagation() default Propagation.REQUIRED;
    
    // 事务隔离级别
    Isolation isolation() default Isolation.DEFAULT;
    
    // 事务超时时间 -1,为永久不超时, 单位是秒
    int timeout() default -1;
    
    // 事务超时时间,可以设置单位,比如 timeoutString = "30s"
    String timeoutString() default "";
    
    // 是否只读事务
    boolean readOnly() default false;
    
    // 对哪些异常进行回滚
    Class<? extends Throwable>[] rollbackFor() default {};
    
    // 对哪些异常进行回滚【异常全限定名】
    String[] rollbackForClassName() default {};
    
    // 对哪些异常不回滚
    Class<? extends Throwable>[] noRollbackFor() default {};
    
    // 对哪些异常不回滚【异常全限定名】
    String[] noRollbackForClassName() default {};
}

rollbackFor和rollbackForClassName的区别,直接来看使用方式。最好使用rollbackFor 可以在编译的时候就帮我买检查是不是对的。

@Transactional(rollbackFor = Exception.class, rollbackForClassName = {"java.lang.Exception"})

@Transactional 注解的参数虽然多,但绝大部分都很好理解。这里主要是来说两个重要且不好理解的参数propagation  和 isolation

@Transactional 实践

在使用 @Transactiona 注解的时候,一定要设置rollbackFor的值,默认情况下是不回滚的检查类异常,比如 IOException、SQLException 等。

在深入理解事务的传播行为之前,我们需要理解三个基本的概念,理解了它们我们就理解了事务传播行为。它们分别是:嵌套事务、新事务、当前事务。

为了理解方便,这里我们先约定一下,有两个事务方法A和B,在A里面调用B。且A事务的定义如下不会改变,B事务的传播行为可能会变。

@Transactional(rollbackFor = Exception.class)
public void A() {
    userMapper.insertUser("A",1);
    sqlTestService.B();
}

public void B() {
    userMapper.insertUser("B",2);
}

项目实践

1. 引入相关依赖

确保在项目的pom.xml(对于Maven项目)或build.gradle(对于Gradle项目)文件中引入了Spring的事务管理依赖。例如,在Maven中可以这样添加:

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-tx</artifactId>
</dependency>

2. 配置事务管理器

在Spring配置文件(如applicationContext.xml)或Java配置类中定义一个事务管理器。对于使用JPA的项目,可以定义JpaTransactionManager

@Bean
public PlatformTransactionManager transactionManager(EntityManagerFactory emf) {
    return new JpaTransactionManager(emf);
}

对于使用JDBC的项目,可以定义DataSourceTransactionManager

@Bean
public PlatformTransactionManager transactionManager(DataSource dataSource) {
    return new DataSourceTransactionManager(dataSource);
}

3. 启用事务注解

在Spring配置文件或Java配置类中启用基于注解的事务管理。可以通过@EnableTransactionManagement注解来实现:

@Configuration
@EnableTransactionManagement
public class AppConfig {
    // 配置数据源、实体管理器工厂和事务管理器等bean
}

4. 使用@Transactional注解

在需要事务支持的服务方法上使用@Transactional注解。例如:

@Service
public class MyService {

    @Autowired
    private MyRepository myRepository;

    @Transactional
    public void performTransactionalOperation() {
        // 业务逻辑,包含数据库操作
        myRepository.save(new Entity());
        // 如果发生异常,事务会回滚
    }
}

5. 高级配置(可选)

根据需要,可以在@Transactional注解中指定更多配置选项,如隔离级别、传播行为、超时时间等:

@Transactional(isolation = Isolation.READ_COMMITTED, propagation = Propagation.REQUIRED, timeout = 30)
public void anotherTransactionalMethod() {
    // 业务逻辑
}

总结

通过上述步骤,Spring框架可以方便地管理事务,从而确保数据的一致性和完整性。主要步骤包括引入依赖、配置事务管理器、启用事务注解和在方法上使用@Transactional注解。根据具体需求,还可以进行高级配置以优化事务管理。

标签:事务,default,Spring,Transactional,开启,注解,public
From: https://blog.csdn.net/2301_76166241/article/details/139636320

相关文章

  • springboot2.6x集成swagger2踩坑点
    最近在用springBoot2.6.13集成swagger2.9.2时出现了几个bug,经过几番尝试后,得出了最终的结论,时间紧可以直接看结论。首次集成swagger2时,启动springboot后的bug:org.springframework.context.ApplicationContextException:Failedtostartbean'documentationPluginsBoots......
  • spring和Mybatis的逆向工程
    目录十二、注解开发1、注解方式单表的增删改查的操作十三、逆向工程13.1、创建逆向工程的步骤⑴添加依赖⑵配置MyBatis的核心配置文件⑶创建逆向工程的配置文件,该文件文件名必须是:generatorConfig.xml13.2测试十四、分页插件14.1、使用步骤14.2分页插件的使用十二、注解开发注......
  • springboot rabbitmq如何保证消息顺序消费
    很多时候,消息的消费是不用保证顺序的,比如借助mq实现订单超时的处理。但有些时候,业务中可能会存在多个消息需要顺序处理的情况,比如生成订单和扣减库存消息,那肯定是先执行生成订单的操作,再执行扣减库存的操作。那么这种情况下,是如何保证消息顺序消费的呢?首先,为了效率,我们可以设置......
  • 【第三篇】SpringSecurity请求流程分析
    简介本篇文章主要分析一下SpringSecurity在系统启动的时候做了那些事情、第一次请求执行的流程是什么、以及SpringSecurity的认证流程是怎么样的,主要的过滤器有哪些?SpringSecurity初始化流程1.加载配置文件web.xml当Web服务启动的时候,会加载我们配置的web.xml文件web.xml......
  • 苹果WWDC24一文总结,携手OpenAi,开启Ai新篇章
    北京时间6月11日凌晨1点,苹果2024年全球开发者大会(WWDC)正式开幕。按照往年惯例,每年的WWDC大会,苹果都会将重心放在对新版系统的介绍上,本次也不例外,苹果发布了包括iOS18、iPadOS18、macOS15以及visionOS2等在内的一系列软件更新。除了例行的系统更新,发布会的最重头大戏就是AI......
  • PVE 开启IOMMU(硬件直通)
    一、前言什么是硬件直通(Passthrough)VT-d、DirectPathI/O,通过DirectPathI/O,虚拟机可以使用I/O内存管理单元访问平台上的物理PCI功能,就是俗称的虚拟化直通,简单理解就是允许宿主机将某些硬件资源的管辖权直接移交给虚拟机,虚拟机会以直通独占的方式使用硬件,宿主机将不能......
  • DockerCompose+Jenkins+Pipeline流水线打包SpringBoot项目(解压安装配置JDK、Maven等)
    场景DockerCompose中部署Jenkins(DockerDesktop在windows上数据卷映射):https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/139491855Docker+Jenkins+Gitee+Maven项目配置jdk、maven、gitee等拉取代码并自动构建以及遇到的那些坑:https://blog.csdn.net/BADAO_LIUMANG_......
  • springboot集成socketio
    1.引入依赖<dependency><groupId>com.corundumstudio.socketio</groupId><artifactId>netty-socketio</artifactId><version>2.0.3</version></dependency>2.基本配置server:port:8081socketio:host:localho......
  • SpringCloudNetflix组件整合
    SpringCloudNetflix组件整合Eureka注册中心Eureka是什么Eureka是netflix的一个子模块,也是核心模块之一,Eureka是一个基于REST的服务,用于定位服务,以实现云端中间层服务发现和故障转移。服务注册与发现对于微服务架构来说是非常重要的,有了服务发现和注册,只需要使用服务的标......
  • springboot3项目的搭建四.3(security登录认证配置)
    security的jwt验证:总体来说,我们加入依赖项,security就已经开始生效了,但是使用的默认的UserDetails和UserDetailsService,一、我们只要继承UserDetailsService,在数据库中查询用户和权限列表,封装成UserDetails的实现类,返回就可以实现,security验证的接管,最多在security配置类中,放行......