spring事务及注解
所属分类 spring
浏览量 17
事务的四大特性(ACID)
原子性(Atomicity):事务里的所有操作,要么全部成功执行,要么全部不执行
一致性(Consistency):事务执行结束后,系统状态会从一个一致状态转变为另一个一致状态
隔离性(Isolation):多个事务同时执行时,彼此之间不会相互干扰
持久性(Durability):一旦事务提交成功,其结果就会永久保存下来
Spring 定义的事务抽象接口
PlatformTransactionManager
事务管理器的核心接口,不同的数据源使用不同的实现类
DataSourceTransactionManager HibernateTransactionManager等
TransactionDefinition
定义事务的隔离级别、传播行为、超时时间和是否只读等属性
TransactionStatus
当前事务的状态,可用于进行事务的提交、回滚等操作
声明式事务管理 @Transactional 注解
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Transactional {
String value() default "";
Propagation propagation() default Propagation.REQUIRED;
Isolation isolation() default Isolation.DEFAULT;
int timeout() default TransactionDefinition.TIMEOUT_DEFAULT;
boolean readOnly() default false;
Class extends Throwable>[] rollbackFor() default {};
String[] rollbackForClassName() default {};
Class extends Throwable>[] noRollbackFor() default {};
String[] noRollbackForClassName() default {};
}
传播行为决定了事务方法在被其他事务方法调用时的事务创建方式
Spring 定义了 7 种传播行为,常见的有以下几种:
REQUIRED(默认):如果当前没有事务,就创建一个新事务;如果已经存在事务,就加入该事务
REQUIRES_NEW:无论当前是否存在事务,都会创建一个新的独立事务,原事务会被挂起
SUPPORTS:如果当前存在事务,就加入该事务;如果不存在事务,就以非事务方式执行
NOT_SUPPORTED:以非事务方式执行,如果当前存在事务,就将其挂起
MANDATORY:必须在一个已存在的事务中执行,如果当前没有事务,就会抛出异常
隔离级别用于控制多个事务之间的可见性,解决脏读、不可重复读和幻读等问题
Spring 支持以下隔离级别:
DEFAULT:使用数据库的默认隔离级别
READ_UNCOMMITTED:允许读取尚未提交的数据,可能会导致脏读
READ_COMMITTED:只能读取已经提交的数据,避免了脏读
REPEATABLE_READ:确保在同一个事务中多次读取同一数据的结果是一致的,解决了不可重复读的问题
SERIALIZABLE:最高的隔离级别,通过完全串行化事务执行来避免幻读,但会降低并发性能
底层实现原理
Spring 的声明式事务是基于 AOP(面向切面编程)实现
事务增强器创建
Spring 会在启动时创建BeanFactoryTransactionAttributeSourceAdvisor事务增强器,该增强器包含:
TransactionAttributeSource:用于解析@Transactional注解的属性
TransactionInterceptor:这是一个方法拦截器,负责处理事务逻辑
代理对象生成:
当 Bean 初始化完成后,Spring 会判断该 Bean 的方法是否标注了@Transactional注解
如果有,就会为其创建代理对象(可以是 JDK 动态代理或者 CGLIB 代理)
事务拦截处理
在目标方法执行前,会根据传播行为和隔离级别开启事务;
方法正常执行完成后,会提交事务;
如果方法抛出异常,会根据rollbackFor和noRollbackFor属性决定是否回滚事务
启用 Spring 声明式事务
@Configuration
@EnableTransactionManagement
public class AppConfig {
// 配置数据源和事务管理器
@Bean
public DataSource dataSource() {
// 配置数据源
}
@Bean
public PlatformTransactionManager transactionManager(DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
}
注意事项
方法可见性要求
@Transactional注解只能应用于public方法,因为 Spring 的 AOP 代理是基于方法调用的可见性来决定是否拦截的
自调用问题
在同一个类中,一个非事务方法调用另一个事务方法,事务不会生效,这是因为自调用不会经过代理对象
异常处理机制
默认情况下,只有RuntimeException及其子类会触发事务回滚
如果需要对受检异常进行回滚,需要通过rollbackFor属性进行指定
@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
@Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.READ_COMMITTED)
// 若当前没有事务,就创建一个新事务;若已有事务,则加入该事务
@Transactional(propagation = Propagation.REQUIRED)
// 无论当前是否存在事务,都创建一个新的独立事务,原事务会被挂起
@Transactional(propagation = Propagation.REQUIRES_NEW)
// 以非事务方式执行,如果当前存在事务,就将其挂起
@Transactional(propagation = Propagation.NOT_SUPPORTED)
// 使用数据库的默认隔离级别
@Transactional(isolation = Isolation.DEFAULT)
// 避免脏读,这是大多数数据库的默认隔离级别
@Transactional(isolation = Isolation.READ_COMMITTED)
// 解决不可重复读问题
@Transactional(isolation = Isolation.REPEATABLE_READ)
// 设置事务超时时间为 30 秒
@Transactional(timeout = 30)
// 标记事务为只读,可进行性能优化
@Transactional(readOnly = true)
// 发生 RuntimeException 或 Error 时回滚事务
@Transactional
// 发生任何异常都回滚事务
@Transactional(rollbackFor = Exception.class)
// 发生特定异常回滚事务,发生另一些异常则不回滚
@Transactional(
rollbackFor = {SQLException.class, DataAccessException.class},
noRollbackFor = {MyBusinessException.class}
)
多数据源事务管理
@Configuration
public class MultiDataSourceConfig {
@Bean(name = "primaryDataSource")
public DataSource primaryDataSource() {
// 配置主数据源
}
@Bean(name = "secondaryDataSource")
public DataSource secondaryDataSource() {
// 配置从数据源
}
@Bean(name = "primaryTransactionManager")
public PlatformTransactionManager primaryTransactionManager(
@Qualifier("primaryDataSource") DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
@Bean(name = "secondaryTransactionManager")
public PlatformTransactionManager secondaryTransactionManager(
@Qualifier("secondaryDataSource") DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
}
// 在服务类中指定使用的事务管理器
@Service
public class MultiDbService {
@Autowired
private UserRepository userRepository;
@Autowired
private ProductRepository productRepository;
// 指定使用主数据源的事务管理器
@Transactional("primaryTransactionManager")
public void updateUser(User user) {
userRepository.save(user);
}
// 指定使用从数据源的事务管理器
@Transactional("secondaryTransactionManager")
public void updateProduct(Product product) {
productRepository.save(product);
}
}
嵌套事务应用场景
通过 Propagation.NESTED 可以实现嵌套事务,嵌套事务是外部事务的一部分,当嵌套事务回滚时,只会回滚当前嵌套事务的操作
@Service
public class OrderService {
@Autowired
private OrderRepository orderRepository;
@Autowired
private PaymentService paymentService;
@Transactional
public void createOrder(Order order) {
orderRepository.save(order);
try {
// 嵌套事务:支付处理
paymentService.processPayment(order);
} catch (PaymentException e) {
// 处理支付异常,但不影响订单创建
logger.error("Payment failed: {}", e.getMessage());
}
}
}
@Service
public class PaymentService {
@Transactional(propagation = Propagation.NESTED)
public void processPayment(Order order) throws PaymentException {
// 处理支付逻辑
if (!paymentGateway.isAvailable()) {
throw new PaymentException("Payment gateway is unavailable");
}
}
}
上一篇
下一篇
12种常见的提示词框架
Python3 VS Python2
FastAPI 和 Flask
《超有趣的 GPT AI 公子逆袭记》笔记
《大数据数学基础(Python语言描述)》 笔记
LangChain原理简介