본문 바로가기
Language/Java

[Java] addBatch/ executeBatch

Writer mintparc 2019. 11. 29.

addBatch


쿼리문을 일괄적으로 처리해야할 때 addBatch메소드를 사용한다. addBatch는 쿼리문을 바로 처리하지 않고 우선적으로 메모리에 하나하나 적재한 후에 일괄적으로 처리한다. 이렇게  한번에 여러건 실행시키기 때문에 속도가 빠르다. 

 

 

 

기존


public int delete (int no) {

		try {
			Class.forName("oracle.jdbc.driver.OracleDriver");
			System.out.println("1.드라이버 연결");
		} catch (ClassNotFoundException e) {
			System.out.println("[ERROR] : 1");
			e.printStackTrace();
		}

		Connection con = null;
		String url = "jdbc:oracle:thin:@localhost:1521:xe";
		String user = "계정";
		String password = "비번";

		try {
			con = DriverManager.getConnection(url, user, password);
			con.setAutoCommit(false);
			System.out.println("2.계정연결");
		} catch (SQLException e) {
			System.out.println("[ERROR] : 2");
			e.printStackTrace();
		}

		PreparedStatement pstm = null;
		String sql = " DELETE FROM TABLE WHERE NO = ? ";
		int res = 0;

		try {
			pstm = con.prepareStatement(sql);
			pstm.setInt(1, no);
			System.out.println("3.쿼리준비");

			res = pstm.executeUpdate();
			System.out.println("4.실행 및 리턴");
			if (res > 0) {
				con.commit();
			}

		} catch (SQLException e) {
			System.out.println("[ERROR] : 3, 4");
			e.printStackTrace();
		} finally {
			try {
				pstm.close();
				con.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}

		return res;

	}

 

기본적으로 DELETE 구문을 실행하는 메소드를 이런 형태로 작성했다. PRIMARY KEY인 no를 파라미터로 넘겨주면 해당  ROW를 지운다. 결과는 pstm.executeqeury에 의해 행의 개수로 리턴되고 res 변수에 담긴다. 만약 res가 0보다 크다면 1개 이상의 ROW가 리턴된 것이므로 이때 커밋한다.

 

기존방식은 쿼리문을 여러번 실행할 경우 PreparedStatement를 열고 닫는 과정을 n번 반복해야하기 때문에 속도가 느릴 수 밖에 없다.

 

 

 

addBatch 이용


예를 들어 한번에 여러 개의 데이터(행)을 삭제해야하는 경우가 있다고 치자.

DELETE FROM TABLE WHERE PK = 1

DELETE FROM TABLE WHERE PK = 2

DELETE FROM TABLE WHERE PK = 3

DELETE FROM TABLE WHERE PK = 4

DELETE FROM TABLE WHERE PK = 5

DELETE FROM TABLE WHERE PK = 6

총 6개의 ROW를 한번에 지워야 한다. 

 

 

public int multiDelete (String[] no) {

		try {
			Class.forName("oracle.jdbc.driver.OracleDriver");
			System.out.println("1.드라이버 연결");
		} catch (ClassNotFoundException e) {
			System.out.println("[ERROR] : 1");
			e.printStackTrace();
		}

		Connection con = null;
		String url = "jdbc:oracle:thin:@localhost:1521:xe";
		String user = "계정";
		String password = "비번";

		try {
			con = DriverManager.getConnection(url, user, password);
			con.setAutoCommit(false);
			System.out.println("2.계정연결");
		} catch (SQLException e) {
			System.out.println("[ERROR] : 2");
			e.printStackTrace();
		}

		PreparedStatement pstm = null;
		String sql = " DELETE FROM TABLE WHERE NO = ? ";
		int res = 0;
        int[] row = 0;								// executeBatch는 결과를 배열로 리턴

		try {
			pstm = con.prepareStatement(sql);
			for(int i = 0; i < no.length; i++){
            	pstm.setString(1, no[i]);			// i번째 no 행을 삭제할 거다
                pstm.addBatch();					// 쿼리문 실행x, 우선 메모리에 하나하나 적재
            }
			System.out.println("3.쿼리준비");

			row = pstm.executeBatch();				// 이때 적재되어있는 쿼리문 모두 실행
			System.out.println("4.실행 및 리턴");
            for(int i = 0; i < row.length; i++){
				if (row[i] == -2) {
					res++;
				}
			}
            
            if(res == row.length) {
				commit(con);
			}
            
		} catch (SQLException e) {
			System.out.println("[ERROR] : 3, 4");
			e.printStackTrace();
		} finally {
			try {
				pstm.close();
				con.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}

		return res;

	}

 

PRIMARY KEY no를 String 배열에 담아서 메소드를 호출하면

배열의 길이만큼 for문이 돌면서 쿼리문을 하나하나 메모리에 차곡차곡 적재한다.

for문이 다 돌고나면 executeBatch메소드가 모아둔 쿼리문을 일괄적으로 처리한다.

 

 

addBatch를 사용할 때 AutoCommit을 false로 하고 사용자가 하나의 트랜잭션으로 처리할 수있다.

 

executeBatch는 결과값을 int배열로 리턴한다. 성공하면 -2, 실패하면 -3을 리턴하는데, 

만약 6개의 쿼리문을 실행시켰고 모두 성공했다면 {-2, -2, -2, -2, -2, -2} 이런 식으로 값이 담겨서 리턴된다.

 

이 안에 담긴 값이 모두 -2일때 커밋을 실행하면 6개의 쿼리문을 하나의 트랜잭션으로 어쩌고 저쩌고,....웅앵웅....

 

 

 

 

 

 

댓글