由于 项目开发,有第三方的回调。。。可能需要用到 多线程,所以 测试了一下 spring的多线程事务。
1, 在 controller 新建一个线程执行 service的 事务情况
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("22>>");
boscRequestLogService.test();
}
}).start();
经过测试, 如果 在 boscRequestLogService.test() 方法里面 ,产生了异常,是可以回滚的。
也就是说, 新线程,在 boscRequestLogService.test() 方法里面的 所有调的方法 都是 对应 spring 声明事务都是可以起作用的,和 controller 没有关系。
2. 在 service 里面的 多线程。
public void test() {
System.out.println("33>>");
BoscRequestLog log = this.getByRequestNo("20171221100422");
log.setReturnErrorMsg("test8888");
this.update(log);
System.out.println("44>>");
int a = 1;
if (a == 2) {
System.out.println("55>>");
throw new NullPointerException("我是空");
}
test2();
}
public void test2() {
new Thread(new Runnable() {
@Override
public void run() {
// 自定义事务控制,达到 之后的业务出现了异常这个充值里面的记录不会回滚
DefaultTransactionDefinition def = new DefaultTransactionDefinition();
def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
// 事物隔离级别,开启新事务,这样会比较安全些。
TransactionStatus status = transactionManager.getTransaction(def); // 获得事务状态
try {
System.out.println("66>>");
BoscRequestLog log = getByRequestNo("20171221100646");
log.setReturnErrorMsg("000");
update(log);
int a = 1;
if (a == 1) {
System.out.println("77>>");
throw new NullPointerException("我是空");
}
transactionManager.commit(status); // 提交事务
} catch (Exception e) {
// TODO Auto-generated catch block
// e.printStackTrace();
System.out.println("...回滚");
transactionManager.rollback(status); // 回滚事务
throw new NullPointerException("我是空");
}
}
}).start();
}
对应 在 service 层里面 建立 多线程执行 方法,那么 声明事务就不会起作用了,出现异常不会回滚的。 所以就需要再 多线程里面 自己控制事务了 所以使用了 DefaultTransactionDefinition def = new DefaultTransactionDefinition(); 。。。
这样在 多线程里面 产生了异常, 多线程里面的方法是可以回滚事务的
不过有一个特殊情况就是 。 比如 上面 test2 方法产生了 异常,抛出去了,在 test 方法 并不能 回滚事务。 也就是 多线程来说, 对于 之前 执行的方法,是不能回滚事务的。声明事务没有作用。 除非 test 方法 自己 定义一个事务控制, try-catch test2 方法,有异常就 回滚就可以。
// spring无法处理thread的事务,声明式事务无效