在企业级应用开发里,数据的一致性和完整性是至关重要的。事务管理就是保障数据在一系列操作中保持正确状态的关键机制。Spring 框架提供了 @Transactional
注解,让我们可以轻松地以声明式的方式来管理事务。下面就分别看看在 Spring 和 Spring Boot 中,@Transactional
是如何发挥作用的。
在 Spring 里使用 @Transactional
注解,首先要配置事务管理器。以 JDBC 事务为例,我们可以在 XML 配置文件里这样配置:
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
bean>
<tx:annotation-driven transaction-manager="transactionManager"/>
这里,DataSourceTransactionManager
是 Spring 提供的用于管理 JDBC 事务的事务管理器,它依赖于一个数据源 dataSource
。
标签则开启了对 @Transactional
注解的支持。
如果使用 Java 配置,代码如下:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import javax.sql.DataSource;
@Configuration
@EnableTransactionManagement
public class AppConfig {
@Bean
public PlatformTransactionManager transactionManager(DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
}
@EnableTransactionManagement
注解同样是开启对 @Transactional
注解的支持,transactionManager
方法创建了一个 DataSourceTransactionManager
实例。
配置好事务管理器后,就可以在服务层的方法上使用 @Transactional
注解了。例如:
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
public class UserService {
@Transactional
public void transferMoney(long fromUserId, long toUserId, double amount) {
// 执行转账业务逻辑
}
}
在这个例子中,transferMoney
方法被 @Transactional
注解标记,意味着这个方法会在一个事务中执行。如果方法执行过程中出现异常,事务会自动回滚,保证数据的一致性。
@Transactional
注解有多个属性,可以对事务的行为进行更细致的控制。
传播行为定义了事务方法和调用它的方法之间事务如何相互作用。常见的传播行为有:
Propagation.REQUIRED
:这是默认值。如果当前存在事务,就加入该事务;如果不存在,就创建一个新事务。Propagation.REQUIRES_NEW
:总是创建一个新事务,如果当前存在事务,就将当前事务挂起。Propagation.NOT_SUPPORTED
:以非事务方式执行操作,如果当前存在事务,就将当前事务挂起。示例代码如下:
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void someMethod() {
// 业务逻辑
}
隔离级别定义了一个事务对其他事务的可见性。常见的隔离级别有:
Isolation.DEFAULT
:使用底层数据库的默认隔离级别。Isolation.READ_COMMITTED
:只允许读取已经提交的数据。示例代码如下:
@Transactional(isolation = Isolation.READ_COMMITTED)
public void anotherMethod() {
// 业务逻辑
}
如果将 readOnly
属性设置为 true
,表示该事务只进行读取操作,可以用于优化性能。
@Transactional(readOnly = true)
public List<User> getUsers() {
// 查询用户列表
return null;
}
timeout
属性指定了事务的超时时间,单位为秒。如果事务执行时间超过该时间,就会自动回滚。
@Transactional(timeout = 10)
public void timeLimitedMethod() {
// 业务逻辑
}
rollbackFor
指定哪些异常发生时事务需要回滚,noRollbackFor
指定哪些异常发生时事务不需要回滚。
@Transactional(rollbackFor = {Exception.class}, noRollbackFor = {CustomException.class})
public void customRollbackMethod() throws Exception {
// 业务逻辑
}
在 Spring 中使用 @Transactional
注解时,要注意以下几点:
@Transactional
注解的方法时,事务才会生效。如果在同一个类的非事务方法里调用事务方法,事务不会生效。RuntimeException
及其子类异常发生时,事务才会回滚。如果想让受检异常也触发事务回滚,可以使用 rollbackFor
属性指定。Spring Boot 为我们提供了自动配置功能,大大简化了事务管理器的配置。只需要在项目中引入相应的依赖,Spring Boot 就会自动配置一个合适的事务管理器。例如,在使用 Spring Data JPA 时,只需要添加以下依赖:
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-data-jpaartifactId>
dependency>
Spring Boot 会自动配置一个 JpaTransactionManager
作为事务管理器。
在 Spring Boot 中使用 @Transactional
注解和在 Spring 中基本相同。只需要在服务层的方法上添加 @Transactional
注解即可。例如:
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
public class ProductService {
@Transactional
public void updateProductStock(long productId, int quantity) {
// 更新产品库存
}
}
在 Spring Boot 中,还可以进行全局事务配置。例如,可以通过配置类来设置默认的事务属性:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.transaction.annotation.TransactionManagementConfigurer;
import javax.sql.DataSource;
@Configuration
@EnableTransactionManagement
public class TransactionConfig implements TransactionManagementConfigurer {
private final DataSource dataSource;
public TransactionConfig(DataSource dataSource) {
this.dataSource = dataSource;
}
@Bean
public PlatformTransactionManager transactionManager() {
return new DataSourceTransactionManager(dataSource);
}
@Override
public PlatformTransactionManager annotationDrivenTransactionManager() {
return transactionManager();
}
}
通过实现 TransactionManagementConfigurer
接口,可以自定义全局的事务管理器。
在 Spring Boot 中进行事务测试也很方便。可以使用 @Transactional
注解结合 @Rollback
注解来保证测试数据不会影响实际数据库。例如:
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.transaction.annotation.Transactional;
@SpringBootTest
@Transactional
public class UserServiceTest {
@Autowired
private UserService userService;
@Test
public void testTransferMoney() {
// 测试转账方法
userService.transferMoney(1L, 2L, 100.0);
}
}
@Transactional
注解保证测试方法在一个事务中执行,@Rollback
注解(默认值为 true
)会在测试方法执行完毕后自动回滚事务,确保测试数据不会持久化到数据库中。
@Transactional
注解是 Spring 和 Spring Boot 中非常强大的事务管理工具,它让我们可以以声明式的方式轻松管理事务。在 Spring 中,需要手动配置事务管理器;而在 Spring Boot 中,借助自动配置功能,事务管理器的配置变得更加简单。在使用 @Transactional
注解时,要注意代理机制、异常处理和嵌套事务等问题,以确保事务管理的正确性和可靠性。
希望通过这篇文章,你能对 @Transactional
注解在 Spring 和 Spring Boot 中的使用有更深入的理解。在实际开发中,合理运用事务管理,能有效保障数据的一致性和完整性,提升应用的稳定性和可靠性。