网络设备/泽成seo网站排名
有一业务场景, 需要初始化所有员工本月的考勤台账. 基本流程是删掉原来的数据 -- >然后重新插入--> 插入月统计表数据 当时场景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() {@Overridepublic 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进行批量插入, 原理一样