开篇
关于Spring 事物的用法,网上已有很多大神进行说明了,我这就不再赘述了,这篇文章我们来玩点别的,大家有什么好的玩法和建议,还望不吝赐教。
事务失败的场景
别人都是怎么使用事物,我在这里说怎么整坏事物,有点添堵的感觉,话虽如此,我还是说得说二句。
无论是声明式事务还是编程式事务,他们实际上都是利用线程私有类来保存Connection,所以,如果我们直接在事务中通过DataSource或原生的方式获取Connection或者在多线程环境中进行数据库操作的时候,因为此时Connection并没有通过事务管理器所管理,所以其事务会失效。
失败示例一:多线程环境
该示例是基于JdbcTemplate做的示例。
@Test
public void testTransactionFail() throws SQLException {
ApplicationContext ctx = new AnnotationConfigApplicationContext(TxConfig.class);
// 获取需要事物控制的service
StudentServiceTransaction studentServiceTransaction =
ctx.getBean(StudentServiceTransaction.class);
DefaultTransactionDefinition transactionDefinition = new DefaultTransactionDefinition();
// 设置读已提交的隔离级别
transactionDefinition.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED);
// 设置事物的传播属性
transactionDefinition.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
// 设置是否是只读模式
transactionDefinition.setReadOnly(false);
// 设置超时时间为30s
transactionDefinition.setTimeout(30);
// 获取配置好的事务管理器
PlatformTransactionManager transactionManager = ctx.getBean(PlatformTransactionManager.class);
// 根据transactionDefinition获取事物状态
TransactionStatus status = transactionManager.getTransaction(transactionDefinition);
try {
Student student = new Student();
// 测试在另一个线程中使用事务
Thread thread = new Thread(() -> {
try {
student.setName("11111111111111");
// 因为在一个新线程中获取的Connection不在事务管理器中管理,所以其不支持事务
studentService.insert(student);
studentService.