在项目编码中会遇到下面的场景,在事务方法中,夹杂着远程调用、消息发送、缓存更新、文件操作等IO操作。
// 注册送积分
@Transactional(rollbackFor = Exception.class)
public void userRegister(..) {
userService.register(..); // 本地DB
remoteCall.addIntegration(...); // 远程调用
...
由于网络存在以下特性:
当网络存在波动或者大量call可能会导致remoteCall.addIntegration
方法耗时过长,导致长事务发生,数据库连接得不到释放,引发无法获取数据库连接,则系统操作就会block住。
所以我们应该把本地事务和其他IO操作剥离
开来,不要影响数据库性能。
Spring提供了很好事务管理机制,主要分为编程式事务和声明式事务两种。我们分表用两种方式来实现。
基于底层的API,如PlatformTransactionManager
、TransactionDefinition
和 TransactionTemplate
等核心接口,开发者完全可以通过编程的方式来进行事务管理。
编程式事务方式需要是开发者在代码中手动的管理事务的开启、提交、回滚等操作。
@Autowired
TransactionManager transactionManager;
// 或
private TransactionManager transactionManager;
private DefaultTransactionDefinition definition;
public UserService(PlatformTransactionManager transactionManager) {
this.transactionManager = transactionManager ;
definition = new DefaultTransactionDefinition() ;
definition.setName("laker") ;
definition.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED) ;
definition.setTimeout(10);
}
public void userRegister() {
DefaultTransactionDefinition definition = new DefaultTransactionDefinition();
definition.setIsolationLevel(TransactionDefinition.ISOLATION_REPEATABLE_READ);
// 事务超时时间单位 秒
definition.setTimeout(30);
TransactionStatus status = transactionManager.getTransaction(definition);
try {
// 事务操作
userService.register(..);
// 事务提交
transactionManager.commit(status);
} catch (DataAccessException e) {
// 事务回滚
transactionManager.rollback(status);
throw e;
}
// 远程调用
remoteCall.addIntegration(..)
}
@Autowired
TransactionTemplate transactionTemplate;
// 或
private TransactionTemplate transactionTemplate ;
public UserService(PlatformTransactionManager transactionManager) {
this.transactionTemplate = new TransactionTemplate(transactionManager) ;
this.transactionTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_NOT_SUPPORTED);
this.transactionTemplate.setTimeout(30); //seconds
}
public void userRegister() {
// 带有返回值
transactionTemplate.execute(new TransactionCallback() {
@Override
public Object doInTransaction(TransactionStatus transactionStatus) {
// 事务操作
userService.register(..);
// 发生异常会自动回滚。也可以通过在 TransactionStatus上调用setRollbackOnly() 来手动触发回滚:
// transactionStatus.setRollbackOnly();
return null;
};
});
// 远程调用
remoteCall.addIntegration(..)
无返回值的调用方式
// 执行无返回值的事务管理
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {
// 事务操作
userService.register(..);
// 发生异常会自动回滚。也可以通过在 TransactionStatus上调用setRollbackOnly() 来手动触发回滚:
// transactionStatus.setRollbackOnly();
}
});
自定义TransactionTemplate
transactionTemplate = new TransactionTemplate(transactionManager);
// 设置事务隔离级别
transactionTemplate.setIsolationLevel(TransactionDefinition.ISOLATION_REPEATABLE_READ);
// 事务传播行为
transactionTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
// 事务超时时间单位秒
transactionTemplate.setTimeout(1000);
// 设置只读事务
transactionTemplate.setReadOnly(true);
spring事务提供扩展可以允许在事务提交后(还有其他阶段),做一些事情
查看
TransactionPhase
,有哪些阶段public enum TransactionPhase { BEFORE_COMMIT, // 事务提交前触发 AFTER_COMMIT, // 事务提交后触发 AFTER_ROLLBACK, // 事务回滚触发 AFTER_COMPLETION // 事务完成后 触发 }
- 1
- 2
- 3
- 4
- 5
- 6
@Transactional(rollbackFor = Exception.class)
public void userRegister(..) {
userService.register(..);
TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
@Override
public void afterCommit() {
//做你想做的业务
remoteCall.addIntegration(..)
}
});
TransactionalEventListener注解
只对声明式事务起作用,对编程式事务无效。仅适用于由PlatformTransactionManager管理的线程绑定事务
@Transactional(rollbackFor = Exception.class)
public void userRegister(..) {
userService.register(..);
applicationEventPublisher.publishEvent(..);
}
@TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT)
public void addIntegration(..){
remoteCall.addIntegration(..)
}