<< 为了健康,将你的身体从酸性变为碱性 | 首页 | 我收藏的链接(40) >>

用jdbc代替hibernate处理大批量的关联数据更新

Spring+hibernate大批量数据处理描述了可以用hibernate快速的处理大批量数据更新:

14.2. 批量更新(Batch updates)

此方法同样适用于检索和更新数据。此外,在进行会返回很多行数据的查询时, 你需要使用 scroll() 方法以便充分利用服务器端游标所带来的好处。

Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
   
ScrollableResults customers = session.getNamedQuery("GetCustomers")
    .setCacheMode(CacheMode.IGNORE)
    .scroll(ScrollMode.FORWARD_ONLY);
int count=0;
while ( customers.next() ) {
    Customer customer = (Customer) customers.get(0);
    customer.updateStuff(...);
    if ( ++count % 20 == 0 ) {
        //flush a batch of updates and release memory:
        session.flush();
        session.clear();
    }
}
   
tx.commit();
session.close();

条件是:
1,将JDBC的批量抓取数量(batch size)参数设置到一个合适值 (其实是500——1000比较合适): 
hibernate.jdbc.batch_size 20

2,在执行批量处理时关闭二级缓存:

hibernate.cache.use_second_level_cache false
但是要是在做了上述操作后,还需要对这些记录关联的另外一个表的记录做一个更新,那用hibernate是有问题的。
因为Hibernate更新一条记录的时候必须首先load查出这条记录,那在批量更新的时候不是很耗费性能?确实是这样的。
所以,在大批量处理更新一个大型数据集合,并且需要修改这个集合关联的数据库表对象时,还是需要JDBC来解决问题。如:

        Connection conn1 = this.getConnection();
        PreparedStatement pstmt1 = null;
        ResultSet rs1 = null;
        String strsql1 = "select workitem_id,work_sheet_no,process_code,process_name,process_ins_id,"
            +"activity_code,activity_name,zone_code,activity_role,run_mode,pre_activity_code,"
            +"pre_activity_name,sendor,sendor_name,participant,participant_name,approve_note,"
            +"start_time,end_time,time_limit,time_limit_unit,over_time,reassign_participant_id,"
            +"form_type,form_id,app_name,urge_date,urger,last_date,last_count,untread,state,remark,"
            +"activity_role_id from wf_workitem r where r.process_code='ec_reprints_invoice_process'";
       
        Connection conn2 = this.getConnection2();
        PreparedStatement pstmt2 = null;
        String strsql2 = "insert into os_currentstep(id,entry_id,step_id,action_id,owner,start_date,"
            +"finish_date,due_date,status,caller) values(seq_os_currentsteps.nextval,?,?,?,?,?,?,?,?,?)";
        int updateNum=0;
        try {
            pstmt1 = conn1.prepareStatement(strsql1);
            pstmt1.setFetchSize(1000);
           
            pstmt2 = conn2.prepareStatement(strsql2);

            rs1 = pstmt1.executeQuery();
            int i=0;
            while (rs1.next()) {
                i++;
                String process_ins_id = rs1.getString("process_ins_id");
                String idsub=process_ins_id.substring(process_ins_id.indexOf("/", 1));
               
                pstmt2.setObject(1, idsub.substring(1,idsub.indexOf("/", 1)));
                pstmt2.setObject(2, getStepIdByStepName(rs1.getString("activity_name"),rs1.getString("process_code")));
                pstmt2.setNull(3,Types.INTEGER);
                pstmt2.setObject(4, rs1.getString("activity_role"));
                Date d=convertStringToDate("yyyy-MM-dd HH:mm:ss", rs1.getString("start_time"));
                if(d==null){
                    pstmt2.setNull(5,Types.DATE);
                }else{
                    pstmt2.setObject(5, new java.sql.Timestamp(d.getTime()));
                }
                pstmt2.setNull(6,Types.DATE);
                pstmt2.setNull(7,Types.DATE);
                if(rs1.getString("participant")==null){
                    pstmt2.setObject(8,"Queued");
                }else{
                    pstmt2.setObject(8,"Underway");
                }
                pstmt2.setObject(9, rs1.getString("participant"));
               
                pstmt2.addBatch();
                if(i%500==0){
                    updateNum=updateNum+pstmt2.executeBatch().length;
                }
            }
            updateNum=updateNum+pstmt2.executeBatch().length;
            System.out.println("更新了当前待办记录条数:"+updateNum);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            cleanConn(conn1,pstmt1,rs1);
            cleanConn(conn2,pstmt2,null);
        }
   
标签 : , , ,



发表评论 发送引用通报