Programming/Java

[Java] JDBC 대용량 데이터 처리 - addBatch, executeBatch, PreparedStatement

OriginMaster 2022. 2. 16. 22:29
반응형
  • 필요성 : 10만건이 넘는 데이터를 DB에 insert할 이슈가 있었다. 기존의 Mybatis를 이용해서 처리하는 과정에서 foreach 생성만 해도 시간 소요가 상당함을 발견했다. Mapper/DAO 처리 대신 JDBC connection을 직접 코딩해주어야 하지만 속도는 훨씬 빠르다.

 

public void insertList(List<LinkedHashMap<String,String>> list, int processAmount) throws Exception {
    Connection con = null;
    PreparedStatement pstmt = null;
    
    StringBuffer sb = new StringBuffer("INSERT INTO T_TABLE( ")
        .append("M_A")
        .append("M_B")
        .append("M_C")
        .append(") VALUES(?, ?, ?)");
    String sql = sb.toString();
        
    try{
        Class.forName("core.log.jdbc.driver.OracleDriver");
        con = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:XE","SCOTT","TIGER");
            
        //exception시 롤백할 수 있도록 auto commit false
        con.setAutoCommit(false);
            
        pstmt = con.prepareStatement(sql);

            
        //prepareStatement for 
        for(int i=0; i < list.size(); i++) {
 			HashMap<String,String> map = list.get(0);
            
            //pstmt.setString(index, param); // sql index 1부터 count
            pstmt.setString(1, map.get("M_A"));
            pstmt.setString(2, map.get("M_B"));
            pstmt.setString(3, map.get("M_C"));
 
            //addBatch 하기
            pstmt.addBatch();
 
            //파라미터 Clear
            pstmt.clearParameters();
            
            // OutOfMemory를 고려하여 processAmount 단위로 커밋
            if( (i % processAmount) == 0){
                // Batch 실행
                pstmt.executeBatch() ;
                // Batch 초기화
                pstmt.clearBatch();
                // 커밋
                con.commit() ;
            }
 
        }
        // Batch 실행
        pstmt.executeBatch() ;
        // Batch 초기화
        pstmt.clearBatch();
        // 커밋
        con.commit() ;
        
    } catch(Exception e){
        this.log.error(e.getMessage());
        //실패시 rollback
        try {
            con.rollback();                
        }catch(Exception e2) {
            this.log.error(e2.getMessage());
        }

    }finally {
        if(pstmt != null){pstmt.close(); pstmt = null;}
        if(con != null){con.close(); con = null;}
    }
       
    }

 

 

 

반응형