赞
踩
在计算机系统中,事务通常指一系列操作,这些操作作为一个单一的工作单元执行,要么全部成功,要么全部失败。事务具有以下四个基本特性,通常被称为 ACID 属性:
事务在应用程序中的使用主要是为了确保数据的完整性和一致性。在多用户环境中,尤其是在并发操作频繁的情况下,事务可以防止数据损坏和冲突。例如,转账操作就是一个典型的事务处理场景,它需要确保转账的原子性和一致性。此外,事务还可以提供以下好处:
事务的管理是任何需要确保数据安全和一致性的应用程序的关键组成部分。
事务管理器是 Spring 框架中用于处理事务的核心组件。它负责协调数据源以确保事务的 ACID 属性得到满足。事务管理器是一个关键组件,它负责协调事务的整个生命周期,确保数据的一致性和完整性。 事务管理器的核心功能包括
Spring Boot 支持多种类型的事务管理器,最常见的是 DataSourceTransactionManager
(适用于 JDBC 操作)和 JpaTransactionManager
(适用于 JPA 操作),也可以自定义事务管理器
//配置事务管理器(创建了一个 DataSourceTransactionManager,它将管理 dataSource 的事务)
@Configuration
public class TransactionConfig {
@Bean
public PlatformTransactionManager transactionManager(DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
}
事务的传播行为定义了一个事务方法是如何关联到其他事务的。Spring 定义了多种传播行为:
REQUIRED
:如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务。REQUIRES_NEW
:创建一个新的事务,并暂停当前的事务。SUPPORTS
:如果当前存在事务,则加入该事务;如果没有,则以非事务方式执行。NOT_SUPPORTED
:以非事务方式执行操作,如果当前存在事务,则暂停当前事务。事务的隔离级别是指事务在并发环境中保护数据不受其他事务影响的能力。Spring 支持以下隔离级别:
DEFAULT
:使用底层数据存储的默认隔离级别。READ_UNCOMMITTED
:允许读取未提交的更改,可能会导致脏读。READ_COMMITTED
:允许读取并提交的更改,可以防止脏读。REPEATABLE_READ
:确保在事务内读取字段的多次读取结果一致。SERIALIZABLE
:确保事务串行执行,以避免并发问题。通过合理配置这些属性,可以确保 Spring Boot 应用程序中的事务处理既安全又高效。
声明式事务管理是通过使用注解或 XML 配置来实现的,它是 Spring Boot 推荐的事务实现方式。最常用的注解是 @Transactional
。
类或方法上添加 @Transactional
注解,可以将一个方法或整个类中的所有公共方法定义为事务性的。Spring 框架会自动为这些方法创建代理,并在方法执行前后添加事务管理逻辑。
@Transactional//在类上添加
public class TransactionalService {
@Transactional//在方法上添加
public void performTransactionalOperation() {
// 业务逻辑
}
}
propagation:定义了事务的传播行为。这决定了方法是如何加入事务的
REQUIRED
(默认值):如果当前没有事务,就新建一个事务;如果已经存在一个事务中,就加入到这个事务中。这是最常用的
SUPPORTS
:如果当前存在事务,就加入到这个事务中;如果没有事务,就以非事务的方式执行。
MANDATORY
:如果已经存在一个事务,就加入到这个事务中;如果没有一个活动的事务,则抛出异常。
REQUIRES_NEW
:新建事务,如果当前存在事务,就把当前事务挂起。
NOT_SUPPORTED
:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
NEVER
:以非事务方式执行,如果当前存在事务,则抛出异常。
NESTED
:如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则表现和 REQUIRED
一样。
isolation:定义了事务的隔离级别,它可以帮助防止事务间的干扰。
DEFAULT
(默认值):这是默认的隔离级别。使用底层数据存储的默认隔离级别,通常是数据库设置的隔离级别。
READ_UNCOMMITTED
:允许事务读取未提交的数据变更,可能会导致脏读、不可重复读和幻读。
READ_COMMITTED
:允许事务读取并提交的数据变更。可以防止脏读,但不可重复读和幻读仍然可能发生。
REPEATABLE_READ
:对同一字段的多次读取结果在同一事务中是一致的,除非数据被事务本身改变。可以防止脏读和不可重复读,但幻读仍然可能发生。
SERIALIZABLE
:确保事务串行执行,以避免脏读、不可重复读和幻读。这是最高的隔离级别,也是最能保证数据完整性的级别,但同时可能会降低并发性能。
timeout:指定了事务的超时时间,默认值为 -1(表示无超时限制)。如果事务超过指定时间未完成,则自动回滚。
readOnly:表示这个事务只读取数据但不更新数据,这可以帮助数据库引擎优化事务。
rollbackFor:定义了哪些异常会触发事务回滚。默认情况下,事务只会在遇到运行时异常和错误时回滚。
noRollbackFor:定义了哪些异常不会触发事务回滚。
transactionManager:指定要使用的事务管理器。当你有多个事务管理器时,可以用这个属性指定一个特定的事务管理器。
实例:
public class TransactionalService {
@Transactional(propagation = Propagation.REQUIRED,
isolation = Isolation.DEFAULT,
timeout = 5,
readOnly = false,
rollbackFor = Exception.class,
noRollbackFor = CustomException.class)
public void performTransactionalOperation() {
// 业务逻辑
}
}
因为 @Transactional
是基于代理的,所以在使用这个注解的时候要避免注解失效的情况。这些场景通常涉及到 Spring AOP 代理的工作方式。
@Transactional
注解被应用在非公共(private、protected 或默认访问级别)的方法上,事务管理将不会被触发@Transactional
注解不会有效@Transactional
注解所在的类没有被 Spring 容器管理,即它不是一个 Spring Bean,那么事务注解也不会生效@Transactional
注解应该使用的事务管理器,事务也可能不会被正确管理。PROPAGATION_NEVER
或 PROPAGATION_NOT_SUPPORTED
编程式事务管理是通过编码来显式管理事务的边界。在 Spring Boot 中,可以使用 TransactionTemplate
或 PlatformTransactionManager
直接控制事务。
TransactionTemplate
提供了一个模板化的方法来管理事务,它封装了事务的开始、提交和回滚的过程,使得开发者可以专注于业务逻辑而不是事务管理的细节。TransactionTemplate
使用 TransactionCallback
接口或其实现类来执行事务操作,提供了一个回调方法 doInTransaction
,在这个方法中编写需要执行的事务性业务逻辑。@Autowired
private TransactionTemplate transactionTemplate;
public void executeOperationWithTransaction() {
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus status) {
// 业务逻辑
}
});
}
PlatformTransactionManager
是 Spring 事务抽象的核心接口,它定义了事务管理的基本方法,如 getTransaction
、commit
和 rollback
。PlatformTransactionManager
可以获得更细粒度的事务控制,例如可以在事务中设置保存点,手动回滚到特定的保存点。// 代码片段 // 手动回滚到特定的保存点 @Autowired private PlatformTransactionManager transactionManager; public void executeOperationWithSavepoint() { // 定义事务属性 DefaultTransactionDefinition def = new DefaultTransactionDefinition(); def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED); // 开始事务 TransactionStatus status = transactionManager.getTransaction(def); Object savepoint = null; try { // 业务逻辑 A // ... // 在此处创建一个保存点 savepoint = status.createSavepoint(); // 业务逻辑 B // ... // 提交事务 transactionManager.commit(status); } catch (SomeSpecificException ex) { // 如果发生特定异常,则回滚到保存点 if (savepoint != null) { status.rollbackToSavepoint(savepoint); } // 可以继续其他操作或重新抛出异常 } catch (Exception ex) { // 如果发生其他异常,则回滚整个事务 transactionManager.rollback(status); throw ex; } }
// 代码片段 // 手动开始和结束事务 @Autowired private PlatformTransactionManager transactionManager; public void performServiceOperation() { // 创建事务定义 TransactionDefinition def = new DefaultTransactionDefinition(); // 开始事务 TransactionStatus status = transactionManager.getTransaction(def); try { // 执行业务逻辑 // ... // 业务逻辑执行成功,提交事务 transactionManager.commit(status); } catch (Exception e) { // 业务逻辑执行出错,回滚事务 transactionManager.rollback(status); throw e; // 可以选择重新抛出异常或进行其他错误处理 } }
在工作中如果想让测试产生的数据不会污染测试数据库或生产数据库,可以通过测试事务来实现,测试事务通常涉及到确保在测试执行后,对数据库所做的更改不会持久化。
@Transactional
注解。这样,每个测试方法执行完毕后,事务都会自动回滚。@RunWith(SpringRunner.class)
@SpringBootTest
@Transactional
public class TransactionalTest {
@Test
public void testMethod() {
// 测试逻辑
}
}
@Rollback
注解,并设置为 true
。@Test
@Rollback(true)
public void testMethod() {
// 测试逻辑
}
在不使用@Transactional 注解和 @Rollback 注解的情况也有办法做到同样的效果,不过这种方式并不是通过事务的回滚,而是使用@Before和@After自动的去清理产生的数据。
@Before
public void setUp() {
// 初始化测试数据
}
@After
public void tearDown() {
// 清理测试数据
}
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。