본문 바로가기
Java

[Java] JDBC 대량 쿼리문 addBatch, executeBatch 실행

by 애리몽 2021. 2. 1.
반응형

addBatch는 쿼리 실행을 하지 않고 쿼리 구문을 메모리에 올려두었다가, 실행 명령(executeBatch)이 있으면 한번에 DB쪽으로 쿼리를 날린다. Array Processing 기능을 활용하면 한 번의 SQL 수행으로 대량의 로우를 동시에 insert/update/delete 할 수 있다.

executeBatch 

 

<실제 적용 예시>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
/**
* 휴가일수 변경사항을 한 번에 수정한다.
* addBatch 이용
*/
public String updateVcatnDaysList(String[] mber_pk_field, String[] use_days_field, String[] used_days_field, String[] vacation_reason_field, String vacation_year, String rgst_id) throws Exception {
        
    String message ="";
    Connection con = null;
    PreparedStatement pstmt = null;
        
    String sql = "UPDATE VACATION SET USE_DAYS = ?, USED_DAYS = ?, REST_DAYS = ? WHERE MBER_PK = ? AND VACATION_YEAR = ?";
        
    try{
        
        Class.forName("core.log.jdbc.driver.OracleDriver");
        con = DriverManager.getConnection("jdbc:oracle:thin:@192.13.135.25:1521:XE","SCOTT","TIGER");
            
        //exception시 롤백할 수 있도록 auto commit 풀어주기
        con.setAutoCommit(false);
            
        pstmt = con.prepareStatement(sql);
            
            
        String MBER_PK = "";
        String USE_DAYS = "";
        String USED_DAYS = "";
        String REST_DAYS = "";
        String VACATION_YEAR = vacation_year;
            
        //비즈니스 로직
        for(int i=0; i < mber_pk_field.length; i++) {
 
            MBER_PK = mber_pk_field[i];
            USE_DAYS = use_days_field[i];
            USED_DAYS = used_days_field[i];
            REST_DAYS = String.valueOf(Float.parseFloat(USE_DAYS) - Float.parseFloat(USED_DAYS));
 
            //남은 휴가일 소수점 없애기
            if(REST_DAYS.charAt(REST_DAYS.length()-1== '0'){
                REST_DAYS = REST_DAYS.substring(0, REST_DAYS.length()-2);
            }
 
            //pstmt.setString(인덱스, 파라미터명); -> sql 순서 꼭 맞게 setString 해주기!!!
            pstmt.setString(1, USE_DAYS);
            pstmt.setString(2, USED_DAYS);
            pstmt.setString(3, REST_DAYS);
            pstmt.setString(4, MBER_PK);
            pstmt.setString(5, VACATION_YEAR);
 
            //addBatch 하기
            pstmt.addBatch();
 
            //파라미터 Clear
            pstmt.clearParameters();
 
        }
 
   
        //다 담은 후 Batch 실행
        pstmt.executeBatch();
            
        //커밋
        con.commit();
            
        //Batch 초기화
        pstmt.clearBatch();
          
        //update 성공 메시지
        message = "U";
                
        } catch(Exception e){
            
            e.printStackTrace();
            
            //실패시 rollback 해줘야함
            try {
                con.rollback();                
            }catch(Exception e1) {
                e1.printStackTrace();
            }
            
            //update 실패 메시지
            message = "F";
          
        }finally {
            
            //꼭 열었던 순서대로 닫아줘야함!!★★★
            if(pstmt != null){pstmt.close(); pstmt = null;}
            if(con != null){con.close(); con = null;}
        
        }
        return message;
    }
    
cs

 

위에 적용 예시에서는 update건수가 그렇게 많지 않아서 한 번에 담아서 실행시켰다.

하지만 건수가 많은 경우는 끊어서 실행시켜줘야한다.

** OutOfMemory를 고려하여 10,000건 단위로 커밋하는 경우

  if( (i % 10000) == 0){

    pstmt.executeBatch() ;

    pstmt.clearBatch();

    con.commit() ;

  }

// 커밋되지 못한 나머지 구문에 대하여 커밋

    pstmt.executeBatch() ;

    con.commit() ;

 

 

 

 


출처: https://fruitdev.tistory.com/111 [과일가게 개발자]

 

[Java] addBatch와 exceuteBatch를 이용한 대용량 데이터 처리

어느날 100만건이 넘는 대용량 데이터를 빠른 시간내에 처리해야 하는 이슈가 있었다. 처음에는 습관처럼 myBatis를 이용하여 데이터 insert를 처리하였는데 데이터를 insert 하는 시간이 생각보다 오

fruitdev.tistory.com

반응형