一、本文主要说明
(1)springboot默认使用cglib动态代理。
(2)springboot默认情况下,同一个Service类内部调用有事务的方法,事物是不生效的。
(3)对于异步处理逻辑,而且要保证事物,怎么做。
二、代码
@RestController
@RequestMapping("/test")
public class TestController {
@Autowired
private TestService testService;
@PostMapping("/testTransaction")
public BaseResponse testTransaction() {
testService.testTransaction();
return BaseResponse.OK;
}
@RequestMapping("/testAsync")
public BaseResponse testAsync() {
testService.testAsync();
return BaseResponse.OK;
}
}
@Service
public class TestService {
@Autowired
private TestDao testDao;
@Autowired
private TestThreadService testThreadService;
public void testTransaction() {
Test test = new Test();
test.setName(UUID.randomUUID().toString());
doSave(test);
}
@Transactional(rollbackFor = Exception.class)
public void doSave(Test test) {
testDao.insert(test);
test.setId(null);
test.setName(UUID.randomUUID().toString());
testDao.insert(test);
int i = 1;
i = i / 0;
}
public void testAsync() {
ThreadUtils.getDefaultThreadFactory().submit(() -> doSave(new Test(null ,UUID.randomUUID().toString())));
ThreadUtils.getDefaultThreadFactory().submit(() -> testThreadService.asyncSaveTest());
}
}
@Service
public class TestThreadService {
@Autowired
private TestDao testDao;
@Transactional
public void asyncSaveTest() {
Test test = new Test();
test.setName("async" + UUID.randomUUID().toString());
testDao.insert(test);
int i = 1;
i = 1 / 0;
}
}
public class ThreadUtils {
private static ThreadPoolTaskExecutor defaultThreadFactory = null;
static {
defaultThreadFactory = createTreadFactory();
}
public static ThreadPoolTaskExecutor getDefaultThreadFactory(){
return defaultThreadFactory;
}
public static ThreadPoolTaskExecutor createTreadFactory() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
// 线程池corePoolSize
executor.setCorePoolSize(5);
// 线程池maxPoolSize
executor.setMaxPoolSize(10);
//队列容量
executor.setQueueCapacity(100);
// 拒绝策略
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
// 正常关闭的时候,等待任务执行完
executor.setWaitForTasksToCompleteOnShutdown(true);
//等待1min
executor.setAwaitTerminationSeconds(60);
// 线程前缀
executor.setThreadNamePrefix("oa-task-");
executor.setKeepAliveSeconds(10);
executor.initialize();
return executor;
}
}
2.1 springboot默认是cglib
2.2 测试同一个service类调用同类方法事务不生效
发送post请求:
http://localhost:8080/test/testTransaction
结果:事务没有生效
2.3 异步线程池执行事务代码,生效事务案例
发送post请求:
http://localhost:8080/test/testAsync
结果:数据库没有插入数据,事务是回滚的
三、总结
(1)springboot默认使用cglib动态代理。
(2)springboot默认情况下,同一个Service类内部调用有事务的方法,事物是不生效的。
要想生效,调用别的类的事务方法。或者说把这块逻辑放到一个公共类执行。
(3)对于异步处理逻辑,而且要保证事物,那么放到别的类,调用类的方法。当然类上面要有事务注解。