@Transactional注解超详细

简介: @Transactional注解超详细

本文前言

@Transactional注解是Spring框架中用于声明式事务管理的关键注解。本文将深入探讨@Transactional注解的作用、使用方式和常见属性,并结合代码实例演示其在实际项目中的应用,以帮助读者更好地理解和使用该注解。

概念说明

 @Transactional注解是Spring框架提供的一个用于声明式事务管理的注解。它可以应用在方法或类上,用于标识需要进行事务管理的方法或类。通过使用@Transactional注解,我们可以更加方便地管理事务,保障数据的一致性和可靠性。在介绍@Transactional注解之前,我们先来了解一下事务的基本概念。事务具有四个基本特性:「原子性 」、「一致性 」、「隔离性 」和「持久性 」。

  • 「原子性 」表示一个事务中的所有操作要么全部成功执行,要么全部失败回滚;
  • 「一致性 」表示事务执行前后数据库的状态保持一致;
  • 「隔离性 」表示多个事务并发执行时,彼此之间是相互隔离的,互不干扰;
  • 「持久性 」表示一旦事务提交,其所做的修改将永久保存在数据库中。

使用说明

 使用@Transactional注解的方式 @Transactional注解可以应用在方法或类上。

1.当应用在方法上时,该方法将被纳入事务管理;

ae5b9b0563cc48e19109a2bfe7b045bf.png

2ad53b54a81640a88842f23550ebc9fa.png

2.当应用在类上时,该类中的所有方法都将被纳入事务管理。

8d418081d4dc4079a6aa16ba7c7496d0.png

9bc07a97996b4dd8994ef94857ac4d79.png

3.常用属性 @Transactional注解有许多属性可供配置,其中一些常用的属性包括事务传播行为、隔离级别和超时设置。事务传播行为用于定义事务方法与其他事务方法的关系;隔离级别用于定义事务方法之间的隔离程度;超时设置用于定义事务方法的最大执行时间。我们可以根据应用程序的需求来灵活配置这些属性。

59875971f5494c04965b8fba727608f5.png

底层实现

public class TransactionalAnnotationProcessor {
    private PlatformTransactionManager transactionManager;
    public TransactionalAnnotationProcessor(PlatformTransactionManager transactionManager) {
        this.transactionManager = transactionManager;
    }
    public Object process(Object target, Method method, Object[] args) throws Throwable {
        Transactional transactional = method.getAnnotation(Transactional.class);
        TransactionStatus transactionStatus = null;
        try {
            // 开启事务
            transactionStatus = transactionManager.getTransaction(new DefaultTransactionDefinition());
            // 执行目标方法
            Object result = method.invoke(target, args);
            // 提交事务
            transactionManager.commit(transactionStatus);
            return result;
        } catch (Exception ex) {
            // 回滚事务
            if (transactionStatus != null) {
                transactionManager.rollback(transactionStatus);
            }
            throw ex;
        }
    }
}

 TransactionalAnnotationProcessor类是一个简化版本的注解解析器。它接收一个PlatformTransactionManager对象作为构造函数的参数,用于管理事务。process()方法接收目标对象、目标方法和方法参数作为参数。该方法首先通过反射获取目标方法上的@Transactional注解,然后根据注解的配置开启事务。接着,执行目标方法,并根据方法执行的结果决定是提交事务还是回滚事务。

注意事项

1.Transactional注解标注方法修饰符为非public

Transactional注解标注方法修饰符为非public
   @Transactional(rollbackFor = Exception.class)
    private void executeInsertSQL(String tableName,String columnName,String placeholderOfColumnName,List<String> fieldNameList,List<Object> valuesOfField ) throws SQLException {
        TransactionStatus transactionStatus=null;
        PlatformTransactionManager transactionManager=null;
        try{
            String sql = "insert into "+tableName+"  (" + columnName + ") values(" + placeholderOfColumnName + ")";
            //获取EntityManager对象
            EntityManager entityManager = Actor.applicationContext.getBean(EntityManager.class);
            transactionManager = Actor.applicationContext.getBean(PlatformTransactionManager.class);
            //手动开启事务
            transactionStatus= transactionManager.getTransaction(new DefaultTransactionDefinition());
            // 使用EntityManager执行JPA操作
            Query nativeQuery = entityManager.createNativeQuery(sql);
            for (int i=0;i<valuesOfField.size();i++){
                nativeQuery.setParameter(fieldNameList.get(i), valuesOfField.get(i));
            }
            nativeQuery.executeUpdate();
            //手动提交事务
            transactionManager.commit(transactionStatus);
        }catch (Exception e){
            if(transactionStatus!=null ){
                //回滚事务
                transactionManager.rollback(transactionStatus);
            }
            e.printStackTrace();
        }
    }

540de0f0372445959e766c8072da56ab.png

Transactional注解标注方法修饰符为非public时,@Transactional注解将会不起作用。因此在方法抛出异常时,nativeQuery.executeUpdate();操作不会进行回滚。如果executeInsertSQL方法改为public的话将会正常开启事务,然后在决定是提交事务还是回滚。

2.在类内部非@Transactional标注的方法,调用类内部@Transactional标注的方法

public void text() throws SQLException {
        List<Object> objects = new ArrayList<>();
        List<String> stringList = new ArrayList<>();
        this.executeInsertSQL("12","21","wzl",stringList,objects);
    }
    /*
     * @description:执行插入的sql语句
     * @author: wuzilong
     * @date: 2023/6/12 17:10
     * @param: [tableName, fieldStr, valueStr, fieldNameList, values]
     * @return: void
     **/
    @Transactional(rollbackFor = Exception.class)
    public void executeInsertSQL(String tableName,String columnName,String placeholderOfColumnName,List<String> fieldNameList,List<Object> valuesOfField ) throws SQLException {
        TransactionStatus transactionStatus=null;
        PlatformTransactionManager transactionManager=null;
        try{
            String sql = "insert into "+tableName+"  (" + columnName + ") values(" + placeholderOfColumnName + ")";
            //获取EntityManager对象
            EntityManager entityManager = Actor.applicationContext.getBean(EntityManager.class);
            transactionManager = Actor.applicationContext.getBean(PlatformTransactionManager.class);
            //手动开启事务
            transactionStatus= transactionManager.getTransaction(new DefaultTransactionDefinition());
            // 使用EntityManager执行JPA操作
            Query nativeQuery = entityManager.createNativeQuery(sql);
            for (int i=0;i<valuesOfField.size();i++){
                nativeQuery.setParameter(fieldNameList.get(i), valuesOfField.get(i));
            }
            nativeQuery.executeUpdate();
            //手动提交事务
            transactionManager.commit(transactionStatus);
        }catch (Exception e){
            if(transactionStatus!=null ){
                //回滚事务
                transactionManager.rollback(transactionStatus);
            }
            e.printStackTrace();
        }
    }

6f6d7040adef4a529d24a1acbffa3d7a.png

调用一个方法在类内部调用内部被@Transactional标注的事务方法,运行结果是事务不会正常开启,nativeQuery.executeUpdate();操作将会保存到数据库不会进行回滚。

3.事务方法内部捕捉了异常,没有抛出新的异常

@Transactional(rollbackFor = Exception.class)
    public void executeInsertSQL(String tableName,String columnName,String placeholderOfColumnName,List<String> fieldNameList,List<Object> valuesOfField ) throws SQLException {
        TransactionStatus transactionStatus=null;
        PlatformTransactionManager transactionManager=null;
        try{
            String sql = "insert into "+tableName+"  (" + columnName + ") values(" + placeholderOfColumnName + ")";
            //获取EntityManager对象
            EntityManager entityManager = Actor.applicationContext.getBean(EntityManager.class);
            transactionManager = Actor.applicationContext.getBean(PlatformTransactionManager.class);
            //手动开启事务
            transactionStatus= transactionManager.getTransaction(new DefaultTransactionDefinition());
            // 使用EntityManager执行JPA操作
            Query nativeQuery = entityManager.createNativeQuery(sql);
            for (int i=0;i<valuesOfField.size();i++){
                nativeQuery.setParameter(fieldNameList.get(i), valuesOfField.get(i));
            }
            nativeQuery.executeUpdate();
            //手动提交事务
            transactionManager.commit(transactionStatus);
        }catch (Exception e){
            System.out.println("抛出了一个异常");
        }
    }

32e1d5d14d7d4d1db1b2b576c35aba8d.png

 运行程序发现,虽然抛出异常,但是异常被捕捉了,没有抛出到方法外, nativeQuery.executeUpdate();操作并没有回滚。

注解扩展

76949b4057c24347a953700b376be3be.png

 以上是一些常用的与@Transactional注解相似的注解,它们都可以用来简化开发、提高代码的可读性和可维护性。您可以根据实际需求选择合适的注解来使用。

总结提升

 @Transactional注解是Spring框架中用于声明式事务管理的关键注解。通过使用@Transactional注解,我们可以更加方便地管理事务,保障数据的一致性和可靠性。在实际项目中,合理使用@Transactional注解可以提高「开发效率 」和代码「可维护性 」。希望本文能帮助读者更好地理解和使用@Transactional注解。

🎯 此文章对你有用的话记得留言+点赞+收藏哦🎯

相关文章
|
XML Java 测试技术
使用 @Transactional 控制事务边界:传播和隔离解释
本文深入解析了 Spring 框架中的 `@Transactional` 注解,重点介绍了事务管理中的传播行为与隔离级别。内容涵盖事务的基本概念、声明式事务管理、回滚机制、传播模式(如 REQUIRED、REQUIRES_NEW 等)及隔离级别(如 READ_COMMITTED、SERIALIZABLE),并通过示例说明如何在实际开发中灵活应用这些特性,以确保数据一致性与系统性能的平衡。适合 Java 开发人员深入理解 Spring 事务机制。
911 1
使用 @Transactional 控制事务边界:传播和隔离解释
|
存储 NoSQL Java
工作 6 年,@Transactional 注解用的一塌糊涂
工作 6 年,@Transactional 注解用的一塌糊涂
626 122
|
Java 关系型数据库 MySQL
深入解析 @Transactional——Spring 事务管理的核心
本文深入解析了 Spring Boot 中 `@Transactional` 的工作机制、常见陷阱及最佳实践。作为事务管理的核心注解,`@Transactional` 确保数据库操作的原子性,避免数据不一致问题。文章通过示例讲解了其基本用法、默认回滚规则(仅未捕获的运行时异常触发回滚)、因 `try-catch` 或方法访问修饰符不当导致失效的情况,以及数据库引擎对事务的支持要求。最后总结了使用 `@Transactional` 的五大最佳实践,帮助开发者规避常见问题,提升项目稳定性与可靠性。
2291 12
|
SpringCloudAlibaba Java 网络架构
【Springcloud Alibaba微服务分布式架构 | Spring Cloud】之学习笔记(七)Spring Cloud Gateway服务网关
【Springcloud Alibaba微服务分布式架构 | Spring Cloud】之学习笔记(七)Spring Cloud Gateway服务网关
2271 0
|
Java Spring
如何通过IDEA查看注解逻辑实现
如何通过IDEA查看注解逻辑实现
1976 0
|
存储 安全 Java
Spring Security 入门与详解
Spring Security 是 Spring 框架中的核心安全模块,提供认证、授权及防护功能。本文详解其核心概念,包括认证(Authentication)、授权(Authorization)和过滤器链(Security Filter Chain)。同时,通过代码示例介绍基本配置,如 PasswordEncoder、UserDetailsService 和自定义登录页面等。最后总结常见问题与解决方法,助你快速掌握 Spring Security 的使用与优化。
3049 0
|
消息中间件 存储 Java
吃透 RocketMQ 消息中间件,看这篇就够了!
本文详细介绍 RocketMQ 的五大要点、核心特性及应用场景,涵盖高并发业务场景下的消息中间件关键知识点。关注【mikechen的互联网架构】,10年+BAT架构经验倾囊相授。
吃透 RocketMQ 消息中间件,看这篇就够了!
|
存储 缓存 NoSQL
Redis中大Key与热Key的解决方案
在工作中,Redis作为一款高性能缓存数据库被广泛应用,但常遇到“大key”和“热key”问题。“大key”指单个键包含大量数据,导致内存消耗高、性能下降及持久化效率降低;“热key”则是频繁访问的键,会引起CPU占用率高、请求阻塞等问题。本文详细分析了这些问题的定义、影响、原因,并提供了相应的解决方案,如合理设置缓存时间和数据结构、拆分大key、采用热点数据分片等方法。
1528 5
Redis中大Key与热Key的解决方案
|
关系型数据库 MySQL
MYSQL 窗口函数
MYSQL 窗口函数
|
XML Java 关系型数据库
注解驱动事务:Spring中基于注解的事务属性配置详解
注解驱动事务:Spring中基于注解的事务属性配置详解
573 0
注解驱动事务:Spring中基于注解的事务属性配置详解

热门文章

最新文章