yewanji
2022-04-24 18:32
采纳率: 39.5%
浏览 147

java多线程批量插入数据报错

问题是这样的,我们有一个业务场景支持excel 批量导入上千条数据,且需要支持整批同时成功或失败,于是我打算将连接改成不自动提交,以手工开启事务形式处理,代码如下

 ExecutorService service = Executors.newFixedThreadPool(5);
    
    @Resource
    SqlSession sqlSession;
    
    @Test
    public void batchInsert() throws SQLException {
        Connection connection = sqlSession.getConnection();
        try {
            // 设置手动提交
            connection.setAutoCommit(false);
            StudentMapper studentMapper = sqlSession.getMapper(StudentMapper.class);
            //执行子线程
            Student stu1 = new Student("张三");
            Student stu2 = new Student("李四");
            Student stu3 = new Student("王五");
            List<Student> students= Arrays.asList(stu1,stu2,stu3);
            List<Callable<Integer>> callableList  = new ArrayList<>();
            for (Student student : students) {
                Callable<Integer> callable=()-> studentMapper.addStudent(student);
                callableList.add(callable);
            }
            List<Future<Integer>> futures = service.invokeAll(callableList);
            for (Future<Integer> future:futures) {
                if (future.get()<=0){
                    connection.rollback();
                    return;
                }
            }
            connection.commit();
            System.out.println("添加完毕");
        }catch (Exception e){
            connection.rollback();
            log.info("error",e);
            throw new RuntimeException("002出现异常");
        }
        Scanner scanner=new Scanner(System.in);
        scanner.next();
    }

mysq和mybatis 配置如下

 @Bean("masterDataSource")
    @Primary
    public DataSource masterDatasource() {
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setDriverClassName(driver);
        dataSource.setUrl(url);
        dataSource.setUsername(userName);
        dataSource.setPassword(password);
        dataSource.setRemoveAbandonedTimeoutMillis(10*1000);
        dataSource.setRemoveAbandoned(true);
        dataSource.setTimeBetweenConnectErrorMillis(10*1000);
        return dataSource;
    }
    
    /***
     * 管理事务
     *
     * */
    @Bean(name = "masterTransactionManager")
    @Primary
    public DataSourceTransactionManager masterTransactionManager() {
        return new DataSourceTransactionManager(masterDatasource());
    }
    
    /***
     * 创建sqlsessionFactory
     *
     * */
    @Bean(name = "masterSqlSessionFactory")
    @Primary
    public SqlSessionFactory masterSqlSessionFactory(@Qualifier("masterDataSource") DataSource masterDataSource)
            throws Exception {
        final SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
        sessionFactory.setDataSource(masterDataSource);
        org.apache.ibatis.session.Configuration config = new org.apache.ibatis.session.Configuration();
        config.setMapUnderscoreToCamelCase(true);
        sessionFactory.setConfiguration(config);
        sessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver()
                .getResources(MAPPER_LOCAL));
        sessionFactory.setPlugins(new SqlCostInterceptor(),new GlobalInterceptor());
        return sessionFactory.getObject();
    }

但现实很残酷,报错了
java.sql.SQLException: connection holder is null
at com.alibaba.druid.pool.DruidPooledConnection.checkStateInternal(DruidPooledConnection.java:1157)
at com.alibaba.druid.pool.DruidPooledConnection.checkState(DruidPooledConnection.java:1148)
at com.alibaba.druid.pool.DruidPooledConnection.commit(DruidPooledConnection.java:743)

  • 写回答
  • 好问题 提建议
  • 追加酬金
  • 关注问题
  • 邀请回答

11条回答 默认 最新

相关推荐 更多相似问题