记一次使用原生jdbc批量插入数据时踩到的坑

有一业务场景, 需要初始化所有员工本月的考勤台账. 基本流程是删掉原来的数据 -- >然后重新插入--> 插入月统计表数据 当时场景900员工, 一个月算30天, 一次初始化要插入2.7W数据.如果dao层框架insert. 要差不多40s. 所以用jdbc进行批量操作

public void initMonth(){
    deleteOld(); //删除原来的数据
    final String sql = "insert into AttendanceUserDay(id,userId,date,remark) " +
                " values(?,?,?,?)";
    Session session = this.sqlDao.getHibernateTemplate().getSessionFactory().openSession();
    session.doWork(new Work() {
            @Override
            public void execute(Connection connection) throws SQLException {
                System.out.println(connection.getAutoCommit());
                PreparedStatement ps = connection.prepareStatement(sql);
                for(int i = 0; i < newObjList.size() ; i++ ){
                    AttendanceUserDay obj = newObjList.get(i);
                    ps.setString(1, obj.getId());
                    ps.setString(2, obj.getUserId());
                    ps.setDate(4, new java.sql.Date (obj.getDate().getTime()));
                    ps.setString(6, obj.getRemark());
                    ps.addBatch();
                    if(i > 0 && i % 1000 == 0){ //每满1000条执行插入一次
                        System.out.println("executeBatch : "+ i);
                        ps.executeBatch();
                        ps.clearBatch();

                    }
                }
                ps.executeBatch();
            }
        });
    //计算并插入月考勤统计表数据....
       
}

该业务方法涉及多表操作,如果自己进行commit会比较麻烦, 系统使用了Spring.故该业务方法的事务由Spring管理了.

测试的时候发现出现阻塞.一直插入不了数据. 排查发现是这里的锅.

Session session = this.sqlDao.getHibernateTemplate().getSessionFactory().openSession();

hibernate的openSession是开启一个新的对话.那么和前面deleteOld()的session是不同一个,而且因为事务给spring管理. deleteOld方法执行后没有提交事务, 这边又起了另外一个session.对同一张表操作.阻塞了.

所以应该使用getCurrentSession.获取当前的session进行操作

Session session = attendanceUserDayDao.getHibernateTemplate().getSessionFactory()
                .getCurrentSession();

也可以使用jdbcTemplate进行批量插入, 原理一样

发布了53 篇原创文章 · 获赞 5 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/qq_40085888/article/details/95474691