wordpress网站防护,手机电影网站源码模板,网站开发国际化,徐州通域网架公司一、问题复现
批量插入时#xff0c;使用多线程对插入数据实现分批插入#xff0c;在service层使用Transactional注解#xff0c;对应方法中线程池中开辟的子线程抛出异常时#xff0c;没有回滚事务。
二、原因分析
事务管理范围不正确#xff1a;Transactional注解仅对…一、问题复现
批量插入时使用多线程对插入数据实现分批插入在service层使用Transactional注解对应方法中线程池中开辟的子线程抛出异常时没有回滚事务。
二、原因分析
事务管理范围不正确Transactional注解仅对当前方法有效如果在方法内创建新的线程或使用线程池等异步操作该方法之外的代码将无法受到事务的管理。因此在使用多线程进行批量操作时需要确保整个批量操作处于同一事务管理范围内。
Spring事务和Java线程池机制的互动问题在使用ThreadPoolExecutor进行批量操作时线程池中的线程和Spring管理的事务并不是同一个线程这可能会导致事务管理器感知不到线程中的异常从而导致事务未能回滚。
三、解决办法
弃用注解样事务改为手动管理事务。
复制代码 SqlSession sqlSession SpringContextUtils.getBean(SqlSessionTemplate.class).getSqlSessionFactory() .openSession();Connection connection sqlSession.getConnection();OfflineExpressRecordExtMapper extMapper sqlSession.getMapper(OfflineExpressRecordExtMapper.class);// 批量插入int taskCount (int) Math.ceil((double) beanList.size() / THREAD_HANDLE);ThreadPoolExecutor executor SpringContextUtils .getBean(offlineExpressRecordThreadPoolExecutor, ThreadPoolExecutor.class);
try {
connection.setAutoCommit(false);
ArrayListFuture? futures new ArrayList();
for (int i 0; i taskCount; i) {
int start i * THREAD_HANDLE;
int end (i 1) * THREAD_HANDLE beanList.size() ? beanList.size() : (i 1) * THREAD_HANDLE;
ListOfflineExpressRecord threadHandleList beanList.subList(start, end);
Future? task executor.submit(() - extMapper.saveBatch(threadHandleList));
futures.add(task);
}// 等待插入完成,检验异常
for (Future? future : futures) {
future.get();
}connection.commit();} catch (Exception e) {log.error(批量导入存储数据过程中出现异常, e);connection.rollback();throw e;
} finally {connection.close();}