一、事务的基本概念
在数据库操作中,事务(Transaction)是一个逻辑单元,由一组操作组成,这些操作要么全部成功,要么全部失败。事务具有以下四个特性,通常简称为 ACID 特性:
- 原子性(Atomicity): 事务中的所有操作要么全部完成,要么全部不完成,不会停留在中间状态。
- 一致性(Consistency): 事务执行前后,数据库的状态必须保持一致。
- 隔离性(Isolation): 并发事务之间互不影响,每个事务都看作数据库的唯一操作。
- 持久性(Durability): 一旦事务提交,其结果是永久性的,即使系统崩溃也不会丢失。
二、声明式事务管理
声明式事务管理是通过注解方式来管理事务,Spring Boot 支持使用 @Transactional
注解来声明事务。
基本使用
import ;
import ;
@Service
public class UserService {
private final UserRepository userRepository;
public UserService(UserRepository userRepository) {
= userRepository;
}
@Transactional
public void updateUser(User user) {
(user);
}
}
在上面的例子中,@Transactional
注解应用于 updateUser
方法,该方法中的所有数据库操作将作为一个事务进行。如果方法中的任何操作失败,整个事务将回滚。
传播行为
传播行为(Propagation Behavior)定义了事务的边界和行为。Spring 提供了多个传播行为选项,常见的包括:
-
REQUIRED
(默认):如果当前存在事务,则加入该事务;如果没有事务,则创建一个新事务。 -
REQUIRES_NEW
:总是创建一个新事务,如果当前存在事务,则将当前事务挂起。 -
SUPPORTS
:如果当前存在事务,则加入该事务;如果没有事务,则以非事务方式执行。 -
NOT_SUPPORTED
:总是以非事务方式执行,如果当前存在事务,则将当前事务挂起。 -
MANDATORY
:如果当前存在事务,则加入该事务;如果没有事务,则抛出异常。 -
NEVER
:总是以非事务方式执行,如果当前存在事务,则抛出异常。 -
NESTED
:如果当前存在事务,则在当前事务中嵌套一个事务(仅支持 JDBC 事务管理器)。
示例:
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void createUser(User user) {
(user);
}
隔离级别
隔离级别(Isolation Level)控制事务操作之间的隔离程度,防止不同事务之间的干扰。常见的隔离级别包括:
-
DEFAULT
:使用数据库的默认隔离级别。 -
READ_UNCOMMITTED
:允许读取未提交的数据,可能导致脏读。 -
READ_COMMITTED
:只读取已提交的数据,防止脏读。 -
REPEATABLE_READ
:确保在一个事务内多次读取数据时数据一致,防止不可重复读。 -
SERIALIZABLE
:最高的隔离级别,完全隔离,防止脏读、不可重复读和幻读。
@Transactional(isolation = )
public void updateUser(User user) {
(user);
}
超时和只读属性
你可以为事务设置超时时间和只读属性:
@Transactional(timeout = 30, readOnly = true)
public User findUserById(Long id) {
return (id).orElse(null);
}
在上面的例子中,事务将设置为只读,并且超时时间为 30 秒。
三、编程式事务管理
除了声明式事务管理,Spring 还支持编程式事务管理,通常使用 TransactionTemplate
或 PlatformTransactionManager
进行控制。
使用 TransactionTemplate
import ;
import ;
import ;
import ;
@Service
public class UserService {
private final TransactionTemplate transactionTemplate;
private final UserRepository userRepository;
public UserService(TransactionTemplate transactionTemplate, UserRepository userRepository) {
= transactionTemplate;
= userRepository;
}
public void updateUser(User user) {
(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus status) {
(user);
}
});
}
}
使用 PlatformTransactionManager
import ;
import ;
import ;
import ;
import ;
@Service
public class UserService {
private final PlatformTransactionManager transactionManager;
private final UserRepository userRepository;
public UserService(PlatformTransactionManager transactionManager, UserRepository userRepository) {
= transactionManager;
= userRepository;
}
public void updateUser(User user) {
DefaultTransactionDefinition def = new DefaultTransactionDefinition();
(TransactionDefinition.PROPAGATION_REQUIRED);
TransactionStatus status = (def);
try {
(user);
(status);
} catch (Exception ex) {
(status);
throw ex;
}
}
}
四、配置事务管理器
在 Spring Boot 中,通常会自动配置 DataSourceTransactionManager
或 JpaTransactionManager
,具体取决于你使用的数据库和持久化框架。
如果需要自定义配置,可以在配置类中定义事务管理器:
import ;
import ;
import ;
import ;
import ;
import ;
@Configuration
@EnableTransactionManagement
public class TransactionConfig {
@Bean
public PlatformTransactionManager transactionManager(DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
@Bean
public TransactionTemplate transactionTemplate(PlatformTransactionManager transactionManager) {
return new TransactionTemplate(transactionManager);
}
}
五、总结
通过 Spring Boot 的事务管理,可以有效地确保数据操作的一致性和完整性。声明式事务管理使用 @Transactional
注解,简单且易于使用。编程式事务管理提供了更细粒度的控制,但需要更多的代码。根据具体需求选择合适的事务管理方式,可以更好地保证应用程序的数据可靠性和性能。