代码演示
声明式事务控制粒度比较大,所以连接对象需要经过比较长的时间才能够回收到连接池中,如果请求很多,同事方法执行比较久,有可能会导致连接池连接对象不足,请求来不及处理。此时如果又想要有事务,并且粒度不能太大,就可以使用编程式事务,而且编程式事务对分布式事务也是可以支持的。
案例1—自动提交
通过 Spring 提供的 TransactionTemplate 工具类操作事务,代码如下:
@Component
public class Person {
@Autowired
private TransactionTemplate template;
public void show(String name) {
System.out.println("Thread.currentThread().getName() = " + Thread.currentThread().getName());
System.out.println("======>show...");
template.execute(status-> {
System.out.println(">>>>>>数据库操作");
template.execute(status1 -> {
System.out.println(">>>>>>数据库操作");
return null;
});
return null;
});
}
}
这个事物执行完逻辑就自动提交,然后归还连接对象。把和数据库打交道的逻辑放到 execute() 逻辑中即可,
案例2—手动提交
有时候可以通过手动控制事务,下面就是借助 Spring 提供的 PlatformTransactionManager 类来手动控制事务的提交、回滚操作。TransactionStatus 类相当于是整个事务流转过程中的状态机。在声明式事务传播中有很大作用,但是编程式事务是没有传播说法的,因为执行完一段逻辑就提交。
@Component
public class Person {
@Autowired
private TransactionTemplate template;
public void show() {
PlatformTransactionManager transactionManager = template.getTransactionManager();
TransactionDefinition definition = new DefaultTransactionDefinition();
TransactionStatus transactionStatus = transactionManager.getTransaction(definition);
try {
System.out.println(">>>>>>数据库操作");
} catch (TransactionException e) {
transactionManager.rollback(transactionStatus);
throw e;
}
transactionManager.commit(transactionStatus);
}
}
总结
在方法中如果存在调用第三方接口时,最好不要放在事务中,调用第三方接口比较耗时,会占用连接对象比较久,造成连接对象资源匮乏。其实编程式事务在源码中还是比较受欢迎的,比如 Seta 框架就用编程式事务来实现。