文章目录
事务支持
Spring Boot 中的事务管理主要依赖于 Spring Framework 提供的功能。Spring 为事务管理提供了两种方式:编程式事务管理和声明式事务管理。在实际开发中,声明式事务管理由于其简洁性和易于使用的特点而更受欢迎。
编程式事务管理
编程式事务管理涉及到在代码中手动控制事务的开始、提交和回滚。这种方式适用于需要精确控制事务边界的情况。例如:
java
@Autowired
private PlatformTransactionManager transactionManager;
public void doWork() {
DefaultTransactionDefinition def = new DefaultTransactionDefinition();
TransactionStatus status = transactionManager.getTransaction(def);
try {
// 执行业务逻辑
// ...
transactionManager.commit(status);
} catch (Exception e) {
transactionManager.rollback(status);
}
}
声明式事务管理
声明式事务管理通过使用 XML 配置或者 @Transactional
注解来实现。这种方式更为常见,因为它简化了事务边界定义,并且不需要在每个方法中显式地管理事务。
使用 @Transactional
注解
要使用 @Transactional
注解,你需要将它应用到需要事务的方法或类上。例如:
java
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
@Transactional
public void createUser(User user) {
userRepository.save(user);
}
}
在这个例子中,createUser
方法会被自动包裹在一个数据库事务中。如果该方法执行过程中发生异常,则事务会自动回滚。
配置事务管理器
为了使用 @Transactional
注解,需要配置一个事务管理器。对于使用 JPA 或 Hibernate 的应用程序,通常会有一个默认的事务管理器,你可以直接使用它。
java
@Configuration
@EnableTransactionManagement
public class AppConfig {
@Autowired
private DataSource dataSource;
@Bean
public PlatformTransactionManager transactionManager() {
return new JpaTransactionManager(entityManagerFactory().getObject());
}
@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
em.setDataSource(dataSource);
em.setPackagesToScan("com.example.domain");
return em;
}
}
@Transactional
的一些属性
readOnly
: 如果设置为 true,则表示事务是只读的,可以提高性能。但需要注意的是,如果数据库驱动不支持只读事务,则不会有任何效果。propagation
: 指定事务传播行为,默认是 REQUIRED,即存在事务则加入,否则新建一个事务。isolation
: 指定事务的隔离级别,默认是数据库的默认隔离级别。timeout
: 指定事务的超时时间(以秒为单位),超过这个时间则自动回滚。rollbackFor
: 指定导致事务回滚的异常类型列表。noRollbackFor
: 指定即使发生异常也不回滚的异常类型列表。
isolation 事务隔离级别
Spring Boot 支持的事务隔离级别主要有以下五种:
-
READ_UNCOMMITTED(读未提交):这是最低的隔离级别,一个事务可以读取到另一个事务未提交的数据。这种隔离级别可能会导致脏读、不可重复读和幻读。
-
READ_COMMITTED(读已提交):这是大多数数据库系统的默认隔离级别。在这个隔离级别下,一个事务只能读取到另一个事务已经提交的数据。这种隔离级别可以避免脏读,但仍然可能导致不可重复读和幻读。
-
REPEATABLE_READ(可重复读):在这个隔离级别下,一个事务在整个过程中可以多次读取到相同的数据行,即使在这个事务执行过程中,其他事务对这些数据行进行了修改或插入。这种隔离级别可以避免脏读和不可重复读,但仍然可能导致幻读。
-
SERIALIZABLE(串行化):这是最高的隔离级别,它要求事务串行执行,即一个事务在执行过程中,其他事务不能对其访问的数据进行修改。这种隔离级别可以避免脏读、不可重复读和幻读,但由于事务串行执行,会导致性能下降。
-
DEFAULT(默认):这是 Spring Boot 默认的事务隔离级别,它的具体值取决于底层数据库系统的默认隔离级别。
在 Spring Boot 中,你可以通过 @Transactional
注解的 isolation
属性来设置事务隔离级别,例如:
java
@Transactional(isolation = Isolation.REPEATABLE_READ)
public void someMethod() {
// ...
}
注意:不同的数据库系统可能支持的事务隔离级别有所不同,具体请参考你所使用的数据库系统的文档。
propagation 事务传播机制
Spring Boot中的事务传播机制定义了在一个方法调用另一个方法时,事务如何传播。Spring提供了7种事务传播行为,分别是:
-
PROPAGATION_REQUIRED:如果当前没有事务,就新建一个事务,如果已经存在一个事务,就加入到这个事务中。这是最常见的选择。
-
PROPAGATION_SUPPORTS:支持当前事务,如果当前没有事务,就以非事务方式执行。
-
PROPAGATION_MANDATORY:使用当前的事务,如果当前没有事务,就抛出异常。
-
PROPAGATION_REQUIRES_NEW:新建事务,如果当前存在事务,把当前事务挂起。
-
PROPAGATION_NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
-
PROPAGATION_NEVER:以非事务方式执行,如果当前存在事务,则抛出异常。
-
PROPAGATION_NESTED:如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,就新建一个事务。
在Spring Boot中,你可以使用@Transactional
注解的propagation
属性来设置事务传播机制,例如:
java
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void someMethod() {
// ...
}
在这个例子中,我们将someMethod
方法的事务传播机制设置为REQUIRES_NEW
,这意味着每次调用这个方法时,都会创建一个新的事务,即使当前已经存在一个事务。
注意:不同的传播机制可能会导致不同的事务行为,因此在选择传播机制时需要根据具体的业务需求进行权衡。