首页 > 其他分享 >@Transactional注解管理事务和手动提交事务

@Transactional注解管理事务和手动提交事务

时间:2024-10-29 18:21:30浏览次数:1  
标签:事务 管理器 Transactional PlatformTransactionManager 注解 public

1、@Transacational注解

(1)注解里面的属性:

  • propagation: 用于设置事务传播属性,该属性类型为Propagation枚举,默认是Propagation.REQUIRED
  • issolation: 用于设置事务的隔离级别,该属性类型为Isolation枚举,默认是Isolation.DEFAULT
  • readOnly: 用于设置该方法对数据库的操作是否是只读,该属性为boolean,默认为false
  • timeout: 用于设置本操作与数据库连接的超时时限,单位为秒,类型int,默认为-1,即没有时限
  • rollbackFor 指定需要回滚的异常类。类型为 Class[],默认值为空数组。当然,若只有一个异常类时,可以不使用数组。
  • rollbackForClassName:指定需要回滚的异常类类名。类型为 String[],默认值为空数组。当然,若只有一个异常类时,可以不使用数组。
  • noRollbackFor:指定不需要回滚的异常类。类型为 Class[],默认值为空数组。当然,若只有一个异常类时,可以不使用数组。
  • noRollbackForClassName: 指定不需要回滚的异常类类名。类型为 - String[],默认值为空数组。当然,若只有一个异常类时,可以不使用数组。

需要注意的是,@Transactional 若用在方法上,只能用于 public 方法上。对于其他非 public 方法,如果加上了注解 @Transactional,虽然 Spring 不会报错,但不会将指定事务织入到该方法中。因为 Spring 会忽略掉所有非 public 方法上的 @Transaction 注解。
若 @Transaction 注解在类上,则表示该类上所有的方法均将在执行时织入事务。

(2)@Transactional注解失效情况

  • 没有被 Spring 容器管理
    如果此时把 @Service 注解注释掉,这个类就不会被加载成一个 Bean,那这个类就不会被 Spring 管理了,事务自然就失效了。
// @Service
public class OrderServiceImpl implements OrderService {
    @Transactional
    public void updateOrder(Order order) {
        // update order
    }
}
  • 用在非public修饰的方法
    @Transactional是基于动态代理的,Spring的代理工厂在启动时会扫描所有的类和方法,并检查方法的修饰符是否为public,非public时不会获取@Transactional的属性信息,这时@Transactional的动态代理对象为空。
  • 多线程调用
    Spring实现事务的原理是通过ThreadLocal把数据库连接绑定到当前线程中,同一个事务中数据库操作使用同一个jdbc connection,新开启的线程获取不到当前jdbc connection
  • 自身调用自身方法
@Service
public class OrderServiceImpl implements OrderService {

    @Transactional
    public void update(Order order) {
        updateOrder(order);
    }
    
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void updateOrder(Order order) {
        // update order
    }   
}

上面的不生效
解决的方案:
[1]注入BeanFactory容器,使用容器获取代理类,然后使用代理类调用事务方法
image
[2]使用@Autowired注解或者@Resource注解注入自己,然后使用注入的代理类去调用事务方法
image
[3]类上面添加注解@EnableAspectJAutoProxy(exposeProxy = true),然后在类中获取当前类的代理类,使用代理类调用事务方法。如果不添加注解的话,可能会出现错误
image

  • 异常被catch“吃了”导致@Transactional失效

  • @Transactional 注解属性 rollbackFor 异常类型设置错误,数据库不支持事务

2、手动启用事务

(1)使用手动事务的场景
1、异步处理业务时,此时业务的事务已经脱离正常的aop机制了,所以需要手动提交事务,来保持业务中多个事务的一致性。
2、在线程中我们也有可能需要事务,这个事务可以使用手动事务。
(2)使用

    @Autowired
    PlatformTransactionManager platformTransactionManager;
    @Test
    void testTransactional(){
        // 获取事务
        DefaultTransactionDefinition defaultTransactionDefinition = new DefaultTransactionDefinition();
        defaultTransactionDefinition.setPropagationBehavior(DefaultTransactionDefinition.PROPAGATION_REQUIRED);
        TransactionStatus transaction = platformTransactionManager.getTransaction(defaultTransactionDefinition);

        // 手动事务
        User user = new User();
        user.setId(13L);
        user.setOpenId("123456");
        user.setUsername("ccgg");
        userRepository.save(user);
        // 事务提交
        platformTransactionManager.commit(transaction);
        try{
            int a = 1/0;
        }catch (Exception e){
            // 事务回滚
            platformTransactionManager.rollback(transaction);
        }
    }

注意:这里引入 PlatformTransactionManager 而不是DataSourceTransactionManager。springboot根据数据库jpa配置自动实现PlatformTransactionManager。数据库组件如果是spring-boot-starter-jdbc,框架会默认注入DataSourceTransactionManager

参考:https://blog.csdn.net/weixin_37862824/article/details/124333511

3、事务管理器

项目中数据库组件如果是spring-boot-starter-jdbc,框架会默认注入DataSourceTransactionManager
如果你添加的是spring-boot-starter-data-jpa依赖,框架会默认注入JpaTransactionManager实例。

JPA的事务管理器和JDBC的事务管理器都实现了PlatformTransactionManager接口

测试项目中使用的是什么类型的事务

//参数platformTransactionManager spring会默认帮我们住进来
@Bean
public Object testBean(PlatformTransactionManager platformTransactionManager){
    System.out.println(platformTransactionManager.getClass().getName());
    return new Object();
}

(1)自定义事务类型
设置Spring的事务类型是DataSourceTransactionManager

@Bean
public PlatformTransactionManager txManager(DataSource dataSource) {
    return new DataSourceTransactionManager(dataSource);//其中dataSource框架会自动为我们注入
}

在Spring容器中,我们手工注解@Bean 将被优先加载,框架不会重新实例化其他的PlatformTransactionManager实现类

@Configuration
public class Profiledemo implements TransactionManagementConfigurer {

	//注入事务管理器2
    @Resource(name="txManager2")
    private PlatformTransactionManager txManager2;

    //创建事务管理器2
    @Bean(name = "txManager2")
    public PlatformTransactionManager txManager2(EntityManagerFactory factory) {
        return new JpaTransactionManager(factory);
    }

    //创建事务管理器1
    @Bean(name = "txManager1")
    public PlatformTransactionManager txManager(DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }

    //实现接口TransactionManagementConfigurer方法,其返回值代表在拥有多个事务管理器的情况下默认使用的事务管理器
    @Override
    public PlatformTransactionManager annotationDrivenTransactionManager() {
        return txManager2;
    }
}

Service使用中指定事务

public class Service{

	//使用value具体指定使用哪个事务管理器
	@Transactional(value="txManager1")
	@Override
	public void xxx() {
	    
	}

	// 在存在多个事务管理器的情况下,默认使用上面annotationDrivenTransactionManager()方法返回的事务管理器
	@Transactional
	public void xxx() {
	    
	}
}

注意:多个数据多个事务管理器,如果没有重写annotationDrivenTransactionManager方法,并且Transactional没有指定value,启动是会报错的

标签:事务,管理器,Transactional,PlatformTransactionManager,注解,public
From: https://www.cnblogs.com/cgy1995/p/18514116

相关文章

  • 在 ASP.NET Core 中使用 EF Core 进行开启事务工作单元(Unit of Work) 仓储层,服务层模式
    在ASP.NETCore中使用EntityFrameworkCore实现一个带有事务的工作单元(UnitofWork)模式的仓储层和服务层,可以确保在执行多个数据库操作时具有原子性。这样,即使某个操作出现错误,所有操作也可以回滚。以下是如何实现这个模式的详细步骤:定义实体类我们首先定义一个简单的实......
  • ssm+vue的班级事务管理系统(有报告)。Javaee项目,ssm vue前后端分离项目。
    演示视频:ssm+vue的班级事务管理系统(有报告)。Javaee项目,ssmvue前后端分离项目。项目介绍:采用M(model)V(view)C(controller)三层体系结构,通过Spring+SpringMvc+Mybatis+Vue+Maven来实现。MySQL数据库作为系统数据储存平台,实现了基于B/S结构的Web系统。界面简洁,操作简单......
  • 主动写入流对@ResponseBody注解的影响
    作者:京东零售柯贤铭问题回溯2023年Q2某日运营反馈一个问题,商品系统商家中心某批量工具模板无法下载,导致功能无法使用(因为模板是动态变化的)商家中心报错(JSON串):{"code":-1,"msg":"失败"} 负责的同事看到失败后立即与我展开讨论(因为不是关键业务,所以不需要回滚,修复即可),我们发......
  • ssm班级事务管理系统+vue
    系统包含:源码+论文所用技术:SpringBoot+Vue+SSM+Mybatis+Mysql免费提供给大家参考或者学习,获取源码请私聊我需要定制请私聊目录第一章绪论 11.1选题背景 11.2选题意义 11.3研究内容 2第二章开发环境 32.1Java语言 32.2MYSQL数据库 32.3Eclipse开发......
  • CodeQL学习笔记(3)-QL语法(模块、变量、表达式、公式和注解)
    最近在学习CodeQL,对于CodeQL就不介绍了,目前网上一搜一大把。本系列是学习CodeQL的个人学习笔记,根据个人知识库笔记修改整理而来的,分享出来共同学习。个人觉得QL的语法比较反人类,至少与目前主流的这些OOP语言相比,还是有一定难度的。与现在网上的大多数所谓CodeQL教程不同,本系列基于......
  • 华为GaussDB数据库包括:事务性(OLTP)数据库、分析型(OLAP)数据库和混合负载(HTAP)数据库
    华为GaussDB数据库包括:事务性(OLTP)数据库、分析型(OLAP)数据库和混合负载(HTAP)数据库。这里需要解释下OLTP、OLAP、HTAP之间的区别,这也是数据库最基本的内容。据库系统一般分为两种类型:一种是面向前台应用的,应用比较简单,但是重吞吐和高并发的OLTP类型;一种是重计算的,对大数据集进行统......
  • GaussDB技术解读——GaussDB架构介绍之全局事务管理层(GTM)关键技术方案
    GTM仅处理全局时间戳请求,64位CSN递增,几乎都是CPU++和消息收发操作。不是每次都写ETCD,而是采用定期持久化到ETCD里,每次写ETCD的CSN要加上一个backup_step(100w),一旦GTM故障,CSN从ETCD读取出来的值保证单调递增。当前GTM只完成CSN++,预估可以支持200M/s请求。GTM处理......
  • GaussDB数据库事务管理
    ​一、引言事务管理是数据库系统中至关重要的一部分,它确保了数据库的一致性和可靠性。在GaussDB数据库中,事务管理不仅遵循传统的ACID特性,还提供了一些高级功能。本文将深入探讨GaussDB数据库事务管理的各个方面。二、事务的基本概念2.1事务的定义事务是数据库操作的基本单元......
  • GaussDB事务存储组件
    事务存储组件云原生数据库支持透明多写,所有节点对等,每个计算节点都可以读写全部的数据页面,事务在本节点执行,没有分布式事务。每个计算节点都有Localbufferpool,采用Remotememorypool扩展计算节点的内存,在多个计算节点之间共享buffer地址,避免页面在多个计算节点之间传来传去。......
  • 【揭秘】如何用ConstraintValidator自定义校验注解,让你的代码更简洁高效!
    在Java中,自定义校验注解(CustomValidationAnnotation)通常用于BeanValidation框架(如HibernateValidator),以便对特定字段或方法参数进行验证。以下是如何创建和使用自定义校验注解的详细步骤和代码示例:1.定义自定义校验注解首先,我们需要定义一个自定义校验注解。这个注解需......