项目中用到了多线程去批量处理一些数据,当时想当然认为只要方法上加上@Transactional注解就好了,实际并未达到想要的处理效果。特此去学习了下关于多线程事务回滚相关方案,参考了网上其他资料,这里整理并记录下学习历程。
站在巨人的肩膀上,我们可以看的更远!
多线程事务怎么回滚?
一、准备相关基础方法
这里以多线程、分批次插入数据库employee表为例子进行演示。
1.线程池配置
/**
* 线程池配置
*/
@Component
public class ExecutorConfig {
private static int maxPoolSize = Runtime.getRuntime().availableProcessors();
private volatile static ExecutorService executorService;
public static ExecutorService getThreadPool() {
if (executorService == null){
synchronized (ExecutorConfig.class){
if (executorService == null){
executorService = newThreadPool();
}
}
}
return executorService;
}
private static ExecutorService newThreadPool(){
int queueSize = 1000;
int corePool = Math.min(10, maxPoolSize);
return new ThreadPoolExecutor(corePool, maxPoolSize, 10000L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<>(queueSize),new ThreadPoolExecutor.AbortPolicy());
}
private ExecutorConfig(){
}
}
2.list切分工具类
/**
* list切分工具类
*/
public class ListUtil {
/**
* 平均拆分list
*
* @param source
* @param n
* @param <T>
* @return
*/
public static <T> List<List<T>> AverageList(List<T> source, int n) {
List<List<T>> result = new ArrayList<>();
int remaider = source.size() % n;
int number = source.size() / n;
//偏移量
int offset = 0;
for (int i = 0; i < n; i++) {
List<T> value;
if (remaider > 0) {
value = source.subList(i * number + offset, (i + 1) * number + offset + 1);
remaider--;
offset++;
} else {
value = source.subList(i * number + offset, (i + 1) * number + offset);
}
result.add(value);
}
return result;
}
}
3.SqlSession工具类
/**
* SqlSession工具类
*/
@Component
public class SqlContext {
@Resource

本文详细描述了在Spring项目中使用多线程批量处理数据时遇到的事务回滚问题,对比了@Transactional注解在多线程下的失效以及使用SqlSession手动控制事务的方法,以确保数据一致性。
最低0.47元/天 解锁文章
341





