SpringBoot - @Transactional注解详解

@Transactional注解提供了事务管理功能,可以在类或方法级别应用。它基于动态代理,支持编程式和声明式事务。默认情况下,仅在遇到运行时异常时回滚事务,但可以通过rollbackFor属性配置。事务传播机制包括REQUIRED、REQUIRES_NEW等,隔离级别有READ_UNCOMMITTED到SERIALIZABLE。文章还讨论了不同场景下的事务回滚情况。

简介

Spring中的@Transactional注解,基于动态代理的机制,提供了一种透明的事务管理机制,方便快捷的解决在开发中碰到的问题,@Transactional 的事务开启 ,或者是基于接口的或者是基于类的代理被创建。Spring为了更好的支撑数据库操作,在框架中支持了两种事务管理的方式:编程式事务和声明式事务,能够保证作单个逻辑工作单元执行的一系列操作,要么同时成功,要么同时失败。

如何使用

(1)可以作用在类和方法上。
(2)建议不要作用在接口或接口的方法上,因为只有使用基于接口的代理时注解才有效。建议作用在实现类的方法上。
(3)当作用在类上时,该类的PUBLIC方法都具有该类型是事务属性,但是使用作用在方法上的注解来覆盖类级别的定义。
(4)方法的访问权限为PUBLIC。
(5)@Transactional(rollbackFor=Exception.class),如果方法上加了这个注解,那么当这个方法抛出异常时(运行时和非运行时)就会回滚,数据库里面的数据也会回滚。如果不配置rollbackFor属性,那么事物只会在遇到运行时异常才会回滚。
(6)默认情况下,SPRING只有在抛出的异常为运行时且为unchecked 异常才会回滚事务,也就是抛出的异常为RuntimeException 的子类(Errors也会)时才会回滚事务,而抛出 checked 异常则不会回滚事务 ,当然可以通过 @Transactional rollbackFor进行配置。

(6.1)checked异常: 一般是指程序不能直接控制的外界情况,是指在编译的时候就需要检查的一类异常,用户程序中必须采用try-catch机制处理或者通过throws交由调用者来处理。这类异常主要是指除了Error以及RuntimeException及其子类之外的异常。
(6.2)unchecked异常:一般是那些不在编译的时就要处理的一类异常。在JAVA体系里,所有的Error以及RuntimeException及其子类都是unchecked异常。
在这里插入图片描述

1. 源码定义
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
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;

	// 事务超时时间设置
	int timeout() default TransactionDefinition.TIMEOUT_DEFAULT;

	String timeoutString() default "";

	boolean readOnly() default false;

	// 导致事务回滚的异常类
	Class<? extends Throwable>[] rollbackFor() default {};

    // 导致事务回滚的异常类名称
	String[] rollbackForClassName() default {};
	
	// 不会导致事务回滚的异常类
	Class<? extends Throwable>[] noRollbackFor() default {};

    // 不会导致事务回滚的异常类名称
	String[] noRollbackForClassName() default {};

}
2. 传播机制
序号机制名称描述
1REQUIRED默认值,如果当前存在事务,则加入该事务,如果当前没有事务,则创建一个新的事务。
2REQUIRES_NEW首先创建一个新的事务,如果当前存在事务,则把当前事务挂起。
3SUPPORTS如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式继续运行。
4NOT_SUPPORTED以非事务方式运行,如果当前存在事务,则把当前事务挂起。
5NEVER以非事务方式运行,如果当前存在事务,则抛出异常。
6MANDATORY如果当前存在事务,则加入该事务;如果当前没有事务,则抛出异常。
7NESTED如果当前存在事务,则创建一个事务作为当前事务的嵌套事务来运行; 如果当前没有事务,则该取值等价于TransactionDefinition.PROPAGATION_REQUIRED。
3. 隔离级别
序号名称描述
1DEFAULT使用后端数据库默认的隔离级别
2READ_UNCOMMITTED读取未提交数据(会出现脏读, 不可重复读)
3READ_COMMITTED读取已提交数据(会出现不可重复读和幻读)
4REPEATABLE_READ可重复读(会出现幻读)
5SERIALIZABLE串行化

使用场景

1. 同一个类
场景1

同一类中有A和B两个方法,A方法上没有@Transactional注解,B方法上有,上层应用通过A方法间接调用B方法,B方法抛出异常,此时A方法和B方法操作都不会回滚。


public void a() {
	b();
}
@Transactional(rollbackFor = Exception.class)
public void b() {
}
场景2

同一类中有A和B两个方法,A方法上有@Transactional注解,B方法上没有,上层应用通过A方法间接调用B方法,B方法抛出异常,此时A方法和B方法操作全部回滚。

@Transactional(rollbackFor = Exception.class)
public void a() {
	b();
}
public void b() {
}
场景3

同一类中有A和B两个方法,A方法和B方法上都有@Transactional注解,上层应用通过A方法间接调用B方法,B方法抛出异常,此时A方法和B方法操作全部回滚。

@Transactional(rollbackFor = Exception.class)
public void a() {
	b();
}
@Transactional(rollbackFor = Exception.class)
public void b() {
}
2. 不同的类
场景1

类1中有A方法,类2中有B方法,A方法上有@Transactional注解,B方法上没有,上层应用通过A方法间接调用B方法,B方法抛出异常,此时A方法和B方法操作全部回滚。

@Transactional(rollbackFor = Exception.class)
public void a() {
	b();
}
public void b() {
}
场景2

类1中有A方法,类2中有B方法,A方法和B方法上都有@Transactional注解,上层应用通过A方法间接调用B方法,B方法抛出异常,此时A方法和B方法操作全部回滚。

@Transactional(rollbackFor = Exception.class)
public void a() {
	b();
}
@Transactional(rollbackFor = Exception.class)
public void b() {
}
场景3

类1中有A方法,类2中有B方法,A方法和B方法上都有@Transactional注解,上层应用通过A方法间接调用B方法,B方法抛出异常,但是A方法捕获了异常,此时B方法操作回滚,A方法抛出异常。

@Transactional(rollbackFor = Exception.class)
public void a() {
	try {
	    b();
    } catch (Exception e) {
        e.printStackTrace();
    }
}
@Transactional(rollbackFor = Exception.class)
public void b() {
}
场景4

类1中有A方法,类2中有B方法,A方法和B方法上都有@Transactional注解,上层应用通过A方法间接调用B方法,B方法抛出异常,但是A方法捕获了异常,此时B方法操作回滚,A方法操作成功。

@Transactional(rollbackFor = Exception.class)
public void a() {
	try {
	    b();
    } catch (Exception e) {
        e.printStackTrace();
    }
}
@Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class)
public void b() {
}
<think>好的,我现在需要帮用户介绍Spring Boot@Transactional注解。用户之前已经询问过Java分布式事务,现在可能是在继续深入学习Spring Boot中的事务管理。首先,我应该回想一下用户之前的对话,了解他们的知识背景,可能他们已经对事务的基本概念有了一定了解,特别是分布式事务,所以现在需要更具体到Spring Boot中的事务实现。 用户的问题是关于@Transactional注解的,我需要详细解释这个注解的作用、使用方式以及相关注意事项。首先,要明确@TransactionalSpring框架提供的声明式事务管理的关键注解,它简化了事务的配置,通过AOP实现。接下来,我需要分点介绍它的核心功能,比如自动提交和回滚规则,隔离级别,传播行为,以及只读事务等。 然后,我需要考虑用户可能的实际应用场景,比如在Service层的方法上添加@Transactional来管理事务。这时候要举一个简单的代码示例,说明如何在Spring Boot项目中使用这个注解。同时,用户可能对注解的参数感兴趣,比如propagation和isolation,这些需要详细解释每个参数的作用和可选值。 另外,用户可能在使用过程中遇到一些常见问题,比如注解不生效的情况。这时候需要总结一些常见的原因,比如方法是否为public、是否被同一个类中的其他方法调用导致AOP失效、异常类型未被正确捕获等。这些注意事项对于用户正确使用@Transactional非常重要,避免踩坑。 还需要比较声明式事务和编程式事务的区别,说明@Transactional属于声明式,而编程式事务则需要使用TransactionTemplate。用户可能想知道两者的适用场景,比如声明式更简洁,编程式更灵活。 最后,要给出最佳实践,比如在Service层使用注解,避免在Controller层使用,以及正确处理异常类型。这些建议能帮助用户更好地应用@Transactional,确保事务管理既有效又高效。 需要确保整个解释清晰易懂,结合代码示例和实际场景,让用户能够快速理解并应用。同时,要注意与之前介绍的分布式事务解决方案(如Seata)进行区分,说明@Transactional主要适用于本地事务,而在分布式系统中可能需要结合其他方案。这样用户就不会混淆两者的使用场景。</think>好的!我来详细介绍一下 Spring Boot 中 **`@Transactional`** 注解的作用、使用方法和注意事项。 --- ### **什么是 @Transactional?** `@Transactional` 是 Spring 框架提供的**声明式事务管理**的核心注解,用于简化数据库事务的配置。通过该注解,可以**自动管理事务的提交、回滚**,无需手动编写 `try-catch` 和事务边界代码(如 `commit()` 或 `rollback()`)。 --- ### **核心功能** 1. **自动事务控制** - 方法执行前开启事务,方法正常结束时提交事务。 - 方法抛出异常时回滚事务(默认对 `RuntimeException` 和 `Error` 回滚)。 2. **灵活配置** - 支持配置事务的**传播行为**、**隔离级别**、**超时时间**、**只读模式**等。 3. **声明式编程** - 基于 AOP 实现,通过注解声明事务规则,代码侵入性低。 --- ### **基本使用** #### 1. **在 Spring Boot 中启用事务** 确保主类或配置类开启事务管理: ```java @SpringBootApplication @EnableTransactionManagement // 启用事务管理(Spring Boot 默认已启用,可省略) public class MyApplication { public static void main(String[] args) { SpringApplication.run(MyApplication.class, args); } } ``` #### 2. **在 Service 层使用注解** 在需要事务管理的方法或类上添加 `@Transactional`: ```java @Service public class UserService { @Autowired private UserRepository userRepository; // 默认事务配置:对 RuntimeException 回滚 @Transactional public void createUser(User user) { userRepository.save(user); // 操作1 sendWelcomeEmail(user); // 操作2(假设可能抛出异常) } // 自定义回滚规则 @Transactional(rollbackFor = Exception.class) public void updateUser(User user) throws Exception { userRepository.update(user); if (someCondition) { throw new Exception("自定义异常"); // 默认不回滚,需通过 rollbackFor 指定 } } } ``` --- ### **关键参数详解** | 参数 | 说明 | |------| | `propagation` | 事务传播行为(默认 `Propagation.REQUIRED`) | | `isolation` | 事务隔离级别(默认 `Isolation.DEFAULT`,使用数据库默认级别) | | `timeout` | 事务超时时间(秒),超时后自动回滚(默认 -1,不超时) | | `readOnly` | 是否开启只读事务(默认 `false`,优化查询性能时设为 `true`) | | `rollbackFor` | 指定触发回滚的异常类型(如 `rollbackFor = {SQLException.class}`) | | `noRollbackFor` | 指定不触发回滚的异常类型 | #### **常见传播行为(Propagation)** - **REQUIRED**(默认):如果当前存在事务,则加入;否则新建一个事务。 - **REQUIRES_NEW**:始终新建事务,挂起当前事务(如果存在)。 - **NESTED**:在当前事务中嵌套子事务(依赖数据库支持,如 MySQL 的保存点)。 - **SUPPORTS**:如果当前有事务,则加入;否则以非事务方式运行。 --- ### **常见问题与注意事项** #### 1. **注解不生效的常见原因** - **方法非 public**:`@Transactional` 只能应用到 public 方法上。 - **自调用问题**:同一类中方法 A 调用方法 B(带有 `@Transactional`),注解会失效(因 AOP 代理机制)。 - **异常被捕获**:若在方法内捕获了异常未重新抛出,事务不会回滚。 - **数据库引擎不支持**:如 MySQL 的 MyISAM 引擎不支持事务,需使用 InnoDB。 #### 2. **事务嵌套与传播行为** - 不同传播行为会影响事务的边界,需根据业务场景谨慎选择。 - 示例:方法 A(`REQUIRED`)调用方法 B(`REQUIRES_NEW`),B 会在独立事务中执行。 #### 3. **声明式 vs 编程式事务** - **声明式**:通过 `@Transactional` 注解(推荐,代码简洁)。 - **编程式**:通过 `TransactionTemplate` 手动控制事务(更灵活)。 --- ### **最佳实践** 1. **在 Service 层使用**:事务管理通常放在业务逻辑层(Service),而非 DAO 或 Controller。 2. **明确指定回滚异常**:根据业务需要配置 `rollbackFor`,避免因异常类型不符导致事务未回滚。 3. **避免长事务**:设置合理的 `timeout`,避免事务长时间占用数据库连接。 4. **只读查询优化**:对查询方法设置 `@Transactional(readOnly = true)`。 --- ### **示例:事务传播行为** ```java @Service public class OrderService { @Transactional(propagation = Propagation.REQUIRED) public void placeOrder(Order order) { // 操作1:扣减库存 inventoryService.deductStock(order); // 操作2:创建订单(独立事务,不受外部事务回滚影响) orderRepository.createOrder(order); } } @Service public class InventoryService { @Transactional(propagation = Propagation.REQUIRES_NEW) public void deductStock(Order order) { // 扣减库存逻辑 } } ``` --- ### **总结** `@Transactional` 是 Spring Boot 中管理数据库事务的核心工具,通过简单注解即可实现复杂的ACID特性。使用时需注意传播行为、异常回滚规则以及常见失效场景,结合业务需求合理配置参数。
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

cloneme01

谢谢您的支持与鼓励!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值