一、本文主要说明 (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();
executor.setCorePoolSize(5);
executor.setMaxPoolSize(10);
executor.setQueueCapacity(100);
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
executor.setWaitForTasksToCompleteOnShutdown(true);
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)对于异步处理逻辑,而且要保证事物,那么放到别的类,调用类的方法。当然类上面要有事务注解。
|