SpringBoot事物管理

使用

Controller

@RestController
@RequestMapping("/transaction")
public class TestTransactionController {

    @Autowired
    private TestService testService;

    @RequestMapping(value = "/test", method = RequestMethod.POST)
    public Result test(FrogTest frog) {
        testService.updateAndInsert(frog);
        return new Result();
    }
}

Service

public interface TestService {

    boolean updateAndInsert(FrogTest frog);

}

@Service
public class TestServiceImpl implements TestService {

    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    private IFrogTestService frogService;

    @Override
    public boolean updateAndInsert(FrogTest frog) {
        try {
            frogService.updateById(frog);
            frogService.save(null);
            return true;
        } catch (Exception e) {
            if(logger.isErrorEnabled()) {
                logger.error("updateAndInsert error:", e);
            }
            throw new MyException(MyExceptionEnum.DATASOURCE_ERROR);
        }
    }
}

模拟先修改在添加,update正常执行,insert时会因error sql报错。如果updateAndInsert方法为一个事物,只需给该方法加上@Transactional注解即可。

    @Override
    @Transactional
    public boolean updateAndInsert(FrogTest frog) {
        try {
            frogService.updateById(frog);
            frogService.save(null);
            return true;
        } catch (Exception e) {
            if(logger.isErrorEnabled()) {
                logger.error("updateAndInsert error:", e);
            }
            throw new MyException(MyExceptionEnum.DATASOURCE_ERROR);
        }
    }

说明

@Transactional注解应用于类和公开的方法,用于类时,该类中所有公开方法都加入事物管理。回滚RuntimeException和Error,但不回滚已检查异常。

注解中几个属性:
value:与transactionManager相同
transactionManager:指定事物管理器
propagation:事物传播
isolation:事物隔离
timeout:超时(只使用于REQUIRED和REQUIRES_NEW传播行为)
readOnly:是否只读
rollbackFor:回滚(以下四项的值为继承Throwable的类或类名)
rollbackForClassName:类名回滚
noRollbackFor:不回滚
noRollbackForClassName:设置类名不回滚

事物特性ACID
原子性(atomicity):一个事务是一个不可分割的工作单位,事务中包括的诸操作要么都做,要么都不做。
一致性(consistency):事务必须是使数据库从一个一致性状态变到另一个一致性状态。一致性与原子性是密切相关的。
隔离性(isolation):一个事务的执行不能被其他事务干扰。即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰。
持久性(durability):持续性也称永久性(permanence),指一个事务一旦提交,它对数据库中数据的改变就应该是永久性的。接下来的其他操作或故障不应该对其有任何影响。

事物传播行为
REQUIRED:支持当前事物,如果不存在则创建一个事物。(默认值)
SUPPORTS:支持当前事务,如果不存在则以非事务方式执行。
MANDATORY:支持当前事务,如果不存在则抛出异常。
REQUIRES_NEW:创建一个新事务,并暂停当前事务(如果存在)。
NOT_SUPPORTED:以非事务方式执行,暂停当前事务(如果存在)。
NEVER:则以非事务方式执行,如果事务存在,抛出异常。
NESTED:如果当前存在事务,则创建一个事务作为当前事务的嵌套事务来运行;如果当前没有事务,则该取值等价于 REQUIRED
【Spring学习34】Spring事务(4):事务属性之7种传播行为

事物隔离级别
DEFAULT:使用基础数据存储的默认隔离级别。(默认值)
READ_UNCOMMITTED:该隔离级别表示一个事务可以读取另一个事务修改但还没有提交的数据。如果发生回滚,则第二个事务将检索到无效行。该级别不能防止脏读和不可重复读,因此很少使用该隔离级别。
READ_COMMITTED:该隔离级别表示一个事务只能读取另一个事务已经提交的数据。该级别可以防止脏读,这也是大多数情况下的推荐值。
REPEATABLE_READ:该隔离级别表示一个事务在整个过程中可以多次重复执行某个查询,并且每次返回的记录都相同。即使在多次查询之间有新增的数据满足该查询,这些新增的记录也会被忽略。该级别可以防止脏读和不可重复读。
SERIALIZABLE:所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰,也就是说,该级别可以防止脏读、不可重复读以及幻读。但是这将严重影响程序的性能。通常情况下也不会用到该级别。

这里引用其他作者描述对脏读、不可重复读、幻读的理解:


作者:Somhu
原文:https://blog.youkuaiyun.com/Somhu/article/details/78775198?utm_source=copy

脏读:所谓的脏读,其实就是读到了别的事务回滚前的脏数据。比如事务B执行过程中修改了数据X,在未提交前,事务A读取了X,而事务B却回滚了,这样事务A就形成了脏读。
也就是说,当前事务读到的数据是别的事务想要修改成为的但是没有修改成功的数据。
不可重复读:事务A首先读取了一条数据,然后执行逻辑的时候,事务B将这条数据改变了,然后事务A再次读取的时候,发现数据不匹配了,就是所谓的不可重复读了。
也就是说,当前事务先进行了一次数据读取,然后再次读取到的数据是别的事务修改成功的数据,导致两次读取到的数据不匹配,也就照应了不可重复读的语义。
幻读:事务A首先根据条件索引得到N条数据,然后事务B改变了这N条数据之外的M条或者增添了M条符合事务A搜索条件的数据,导致事务A再次搜索发现有N+M条数据了,就产生了幻读。
也就是说,当前事务读第一次取到的数据比后来读取到数据条目少。


注意的问题

Service

    @Override
    @Transactional
    public boolean updateAndInsert(FrogTest frog) {
        try {
            frogService.updateById(frog);
            frogService.save(null);
            return true;
        } catch (Exception e) {
            if(logger.isErrorEnabled()) {
                logger.error("updateAndInsert error:", e);
            }
            throw new MyException(MyExceptionEnum.DATASOURCE_ERROR);
        }
    }

    @Override
    public void update(FrogTest frog) {
        updateAndInsert(frog);
    }

如果将Service层修改为如上,Controller层先调用update方法,update在调用updateAndInsert方法,尽管后者加了@Transactional注解,方法中两个操作并不是一个事物。
因为@Transactional 的事务开启 ,或者是基于接口的或者是基于类的代理被创建。所以在同一个类中一个方法调用另一个方法有事务的方法,事务是不会起作用的。
参考:https://zhuanlan.zhihu.com/p/38208248
经过测试,update方法加上注解,updateAndInsert不加,事物起作用。

<think> 首先,用户的问题是关于SpringBoot事务管理的,包括使用方法、原理及注意事项。我需要根据提供的引用内容来构建回答。 引用内容: - [^1]: 解释了SpringBoot事务管理基于Spring框架,遵循ACID特性,特别是原子性。 - [^2]: 详细介绍了事务管理的基本概念,编程式事务管理使用`TransactionTemplate`或`PlatformTransactionManager`。 - [^3]: 讨论了在复杂情况下指定不同的事务管理器,比如在多个数据源时。 用户的具体问题:"SpringBoot事务管理的使用方法、原理及注意事项"。所以我需要覆盖这三个方面: 1. **使用方法**:如何在实际代码中使用事务管理。 2. **原理**:事务管理背后的机制,如何实现ACID特性。 3. **注意事项**:在使用时需要注意的点,如事务传播、隔离级别、回滚规则等,基于引用的内容。 回答结构: - 由于系统指令要求结构清晰,逐步解决问题,我将组织回答为几个部分。 - 使用中文回答。 - 行内数学表达式用`$...$`,但在这个主题中可能不涉及数学表达式,除非有计算相关的内容。事务管理通常不涉及数学公式,所以我可能不需要使用数学表达。 - 独立公式用`$$...$$`,但同样,不太可能用到。 - 生成相关问题:在回答末尾添加相关问题。 - 引用标识:在引用段落末尾添加`[^1]`等。引用的来源是用户提供的,所以我需要整合这些引用。 整合引用: - 引用[^1]:事务管理的机制和ACID特性。 - 引用[^2]:编程式事务管理示例。 - 引用[^3]:指定不同事务管理器。 我需要确保回答真实可靠,基于这些引用。同时,用户提到“参考站内引用”,但在这个上下文中,似乎是模拟的引用。我应该引用它们作为参考。 回答大纲: 1. **引言**:简要介绍SpringBoot事务管理。 2. **原理**:解释事务管理的工作原理,基于Spring框架和ACID特性。 3. **使用方法**: - 编程式事务管理(如引用[^2]所示)。 - 声明式事务管理(可能没有直接引用,但我知道SpringBoot中常用`@Transactional`注解)。 4. **注意事项**:包括事务传播行为、隔离级别、回滚规则、多数据源处理(如引用[^3]所示)。 5. **总结**。 6. **相关问题**:生成几个相关问题。 由于引用中没有提到声明式事务管理,但我知道它是SpringBoot中更常见的方式。我应该补充知识:声明式事务管理使用`@Transactional`注解。 注意事项: - 事务传播:例如,`@Transactional(propagation=Propagation.REQUIRED)`。 - 隔离级别:如`@Transactional(isolation=Isolation.READ_COMMITTED)`。 - 回滚规则:默认在RuntimeException时回滚,可以自定义。 - 在多个数据源时,需要指定事务管理器。 生成相关问题: - 类似示例中的格式,提出3个相关问题,比如关于性能优化、常见问题等。 最终回答结构: - 使用标题或小节来组织。 - 在引用段落末尾添加引用标识。 - 确保语言流畅,帮助用户逐步理解。 开始草拟回答: **SpringBoot事务管理详解** 在SpringBoot中,事务管理是确保数据库操作原子性的关键机制。它基于Spring框架的事务抽象层,简化了事务控制。 **原理** SpringBoot的事务管理机制实质上是基于Spring框架的事务处理机制,其主要目的是确保一系列数据库操作要么全部成功,要么全部失败(回滚),从而维护数据的完整性和一致性[^1]。事务遵循ACID四大特性:原子性、一致性、隔离性和持久性。其中,原子性是指事务内的操作要么全部完成,要么全部不执行。 **使用方法** SpringBoot支持两种类型的事务管理:编程式事务管理和声明式事务管理。 1. **编程式事务管理**:使用`TransactionTemplate`或直接使用`PlatformTransactionManager`来手动管理事务。例如: ```java @Service public class TransactionalService { @Autowired private TransactionTemplate transactionTemplate; public void transactionalMethod() { TransactionStatus status = transactionTemplate.getTransactionManager().getTransaction(new DefaultTransactionDefinition()); try { // 执行业务逻辑 transactionTemplate.commit(status); } catch (Exception e) { transactionTemplate.rollback(status); } } } ``` 这种方法需要在代码中显式地开始事务、提交事务或者回滚事务[^2]。 2. **声明式事务管理**:更常见的做法是使用`@Transactional`注解。在方法上添加此注解,Spring会自动管理事务。 ```java @Service public class UserService { @Transactional public void saveUser(User user) { // 执行业务逻辑,如保存用户到数据库 } } ``` 声明式事务管理简化了代码,不需要手动控制事务边界。 **注意事项** 在使用SpringBoot事务管理时,需要注意以下几点: - **事务传播行为**:定义事务如何传播,例如`REQUIRED`(如果当前没有事务,就新建一个事务)或`SUPPORTS`(如果当前有事务,就加入该事务)。可以通过`@Transactional(propagation = Propagation.REQUIRED)`指定。 - **隔离级别**:控制事务之间的可见性,如`READ_COMMITTED`。使用`@Transactional(isolation = Isolation.READ_COMMITTED)`设置。 - **回滚规则**:默认情况下,事务在抛出`RuntimeException`或`Error`时回滚。可以通过`@Transactional(rollbackFor = Exception.class)`自定义回滚异常。 - **多数据源事务**:当系统中有多个数据源时,需要为每个数据源配置事务管理器,并在`@Transactional`中指定使用哪个管理器,例如`@Transactional(value = "transactionManagerPrimary")`[^3]。 - 避免在事务方法中调用另一个事务方法时出现自调用问题(因为代理机制)。 - 确保事务方法不被定义为`private`,否则代理可能失效。 **总结** SpringBoot的事务管理通过声明式或编程式方式,提供了强大的事务控制能力,确保数据一致性。理解其原理和正确使用可以提高应用的可靠性。 §§相关问题§§ 1. SpringBoot中如何处理分布式事务? 2. `@Transactional`注解有哪些常用属性及其作用? 3. 在SpringBoot中,事务传播行为有哪些类型? 确保引用添加: - 在引用[^1]的地方添加。 - 在引用[^2]的地方添加。 - 在引用[^3]的地方添加。 在回答中,我会自然地添加引用标识。 </think>### SpringBoot事务管理详解 SpringBoot的事务管理机制基于Spring框架的事务抽象层,通过简化配置和自动管理,确保数据库操作的原子性、一致性、隔离性和持久性(ACID)。以下从使用方法、原理和注意事项三个方面详细说明。回答基于提供的引用内容[^1][^2][^3],确保内容真实可靠。 #### 1. **使用方法** SpringBoot支持两种事务管理方式:编程式事务管理和声明式事务管理。声明式事务更常用,因为它更简洁。 - **声明式事务管理(推荐)** 使用`@Transactional`注解在方法或类上,SpringBoot会自动管理事务边界(开始、提交或回滚)。示例代码: ```java @Service public class UserService { @Autowired private UserRepository userRepository; @Transactional // 声明事务,默认使用当前数据源的事务管理器 public void createUser(User user) { userRepository.save(user); // 数据库操作 // 其他业务逻辑 } } ``` 在此示例中,`@Transactional`注解确保`createUser`方法中的操作要么全部成功提交,要么全部回滚[^2]。 - **编程式事务管理** 手动控制事务,适用于复杂场景。使用`TransactionTemplate`或`PlatformTransactionManager`: ```java @Service public class OrderService { @Autowired private TransactionTemplate transactionTemplate; public void processOrder() { transactionTemplate.execute(status -> { try { // 执行业务逻辑(如订单处理) return true; // 成功时提交事务 } catch (Exception e) { status.setRollbackOnly(); // 失败时回滚 return false; } }); } } ``` 这种方法需要显式处理事务状态,灵活性高但代码较冗长[^2]。 - **多数据源场景** 当系统有多个数据源时,需为每个数据源配置独立的事务管理器,并在`@Transactional`中指定: ```java @Transactional(value = "transactionManagerPrimary") // 指定主数据源的事务管理器 public void multiDataSourceOperation() { // 操作多个数据源 } ``` 配置详情可参考多数据源设置[^3]。 #### 2. **原理** SpringBoot事务管理的核心原理基于Spring框架的代理机制和ACID特性: - **ACID特性实现**: - **原子性(Atomicity)**:事务内的操作要么全部成功(提交),要么全部失败(回滚)。这是通过事务管理器(如`PlatformTransactionManager`)协调数据库连接实现的[^1]。 - **一致性(Consistency)**:事务确保数据从一种有效状态转换到另一种有效状态(如约束检查)。 - **隔离性(Isolation)**:控制并发事务的可见性,防止脏读、不可重复读等问题。SpringBoot支持设置隔离级别(如`READ_COMMITTED`)。 - **持久性(Durability)**:事务提交后,更改永久保存到数据库。 - **底层机制**: - 代理模式:Spring使用AOP(面向切面编程)为`@Transactional`方法创建代理。调用方法时,代理先启动事务,再执行业务逻辑,最后根据结果提交或回滚。 - 事务管理器:底层依赖JDBC或JPA的事务API。SpringBoot自动配置`DataSourceTransactionManager`用于单数据源场景。 - 事务传播:定义事务如何嵌套或加入现有事务。例如,`Propagation.REQUIRED`(默认)表示如果当前无事务,则新建一个。 #### 3. **注意事项** 使用事务管理时需注意以下关键点,以避免常见问题: - **事务传播行为**: 通过`@Transactional(propagation = Propagation.REQUIRED)`指定。常见类型: - `REQUIRED`:加入当前事务(或新建)。 - `REQUIRES_NEW`:始终新建事务。 - `NESTED`:嵌套在当前事务中(部分数据库支持)。 错误配置可能导致事务不生效或死锁。 - **隔离级别设置**: 使用`@Transactional(isolation = Isolation.READ_COMMITTED)`控制并发问题。默认级别取决于数据库,但建议显式设置以避免脏读。 - **回滚规则**: - 默认回滚:仅在`RuntimeException`或`Error`时回滚。 - 自定义回滚:通过`@Transactional(rollbackFor = Exception.class)`指定需回滚的异常。 - 避免在catch块中吞没异常,否则事务可能无法回滚[^2]。 - **多数据源事务**: - 每个数据源需独立配置事务管理器(如`@Bean public PlatformTransactionManager transactionManagerPrimary()`)。 - 在`@Transactional`中明确指定管理器名称(如`value="transactionManagerSecondary"`),否则可能使用默认管理器导致错误[^3]。 - **其他注意事项**: - **方法可见性**:`@Transactional`方法不能为`private`或`final`,否则代理失效(需声明为`public`)。 - **自调用问题**:类内部方法调用(如`this.method()`)会绕过代理,应避免或使用`AopContext.currentProxy()`解决。 - **性能影响**:事务范围不宜过大,减少锁竞争。避免在事务中进行耗时操作(如网络请求)。 - **测试**:使用`@SpringBootTest`和`@Transactional`注解进行单元测试,确保事务可回滚。 #### 总结 SpringBoot事务管理通过声明式或编程式方式,简化了数据一致性保障。原理上依赖Spring的代理和ACID特性,使用时需关注传播行为、隔离级别和多数据源配置。合理应用可提升系统可靠性,避免数据不一致问题。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值