기본 설정은 무조건 자동커밋되므로 중간에 에러가 생겨도 돌아갈 수가 없다.
그래서 한번에 커밋할 수 있도록 수동커밋으로 변경.
iscommit == false는 커밋이 되지 않았다는 뜻이고, 어디선가 오류가 발생하면 예외처리로 넘어가는데
원래 상태로 롤백하기 위해 주었다.
package ex02.jdbcp.batchquery;
import java.sql.*;
public class BatchInsertEx {
static {
try {
Class.forName("oracle.jdbc.driver.OracleDriver");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
// 2. url, id, pass
String url = "jdbc:oracle:thin:@localhost:1521:xe";
String id = "bitTest";
String pass = "bitTest";
// 3. 관련 클래스 변수 선언
Connection con = null;
Statement stmt = null;
ResultSet rs = null;
boolean isCommit = false; //커밋이 완료되었는지의 여부
try {
// 4. 오라클 서버 접속 객체 생성
con = DriverManager.getConnection(url, id, pass);
// 5. sql문 실행 객체 생성
stmt = con.createStatement();
// 6. 배치 쿼리 작성(한번에 여러개의 sql문을 작성하고 동시에 실행한다)
// 6.1 jdbc의 DML문 이후에 자동커밋 설정을 수동커밋으로 변경한다.
con.setAutoCommit(false);
stmt.addBatch("INSERT INTO professor (pno, pname, section, orders, hiredate) VALUES ('1001','송강','화학','정교수',TO_DATE('1999-12-20:09:13:25','YYYY-MM-DD:HH24:MI:SS'))");
stmt.addBatch("INSERT INTO professor (pno, pname, section, orders, hiredate) VALUES ('1002','곤송승','화학','정교수',TO_DATE('1998-01-20:09:13:25','YYYY-MM-DD:HH24:MI:SS'))");
stmt.addBatch("INSERT INTO professor (pno, pname, section, orders, hiredate) VALUES ('1003','진명','화학','정교수',TO_DATE('1997-08-20','YYYY-MM-DD'))");
stmt.addBatch("INSERT INTO professor (pno, pname, section, orders, hiredate) VALUES ('1004','시진','화학','부교수',TO_DATE('2000-12-20:09:13:25','YYYY-MM-DD:HH24:MI:SS'))");
stmt.addBatch("INSERT INTO professor (pno, pname, section, orders, hiredate) VALUES ('1005','노지심','화학','부교수',TO_DATE('1995-03-20:09:13:25','YYYY-MM-DD:HH24:MI:SS'))");
//7.실행
int[] counts = stmt.executeBatch(); //각각의 sql문이 몇개행에 적용되었는지
isCommit = true; //커밋이 완료되었다는 의미
con.commit(); //"commit" sql문 실행
con.setAutoCommit(true); //수동커밋 -> 자동커밋 설정 변경
} catch (SQLException e) {
e.printStackTrace();
} finally {
// 전체 5개 sql문이 정상실행되지 않으면 모두 롤백(취소) 처리 한다.
try {
if(!isCommit) con.rollback(); //true가 아니면 롤백해라. 문장 실행 중에 하나라도 문제가 생기면 catch를 거쳐 finally로 가서 rollback을 해버린다.
//아래 부분은 객체 생성이 된 객체들을 닫기 처리한다.
if(rs != null) rs.close();
if(stmt != null) stmt.close();
if(con != null) con.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
addBatch는 쿼리 실행을 하지 않고
쿼리 구문을 메모리에 올려두었다가, 실행 명령이 있으면 한번에 DB쪽으로 쿼리를 날린다.
-은행 예제
counts는 왜 배열이어야하는지..?
executeBatch() 메소드가 업데이트 수를 세서 배열로 리턴하니까..
package ex02.jdbcp.batchquery;
import java.sql.*;
public class BatchInsertEx {
static {
try {
Class.forName("oracle.jdbc.driver.OracleDriver");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
// 2. url, id, pass
String url = "jdbc:oracle:thin:@localhost:1521:xe";
String id = "bitTest";
String pass = "bitTest";
// 3. 관련 클래스 변수 선언
Connection con = null;
Statement stmt = null;
boolean isCommit = false; //커밋이 완료되었는지의 여부
try {
// 4. 오라클 서버 접속 객체 생성
con = DriverManager.getConnection(url, id, pass);
// 5. sql문 실행 객체 생성
stmt = con.createStatement();
// 6. 배치 쿼리 작성(한번에 여러개의 sql문을 작성하고 동시에 실행한다)
// 6.1 jdbc의 DML문 이후에 자동커밋 설정을 수동커밋으로 변경한다.
con.setAutoCommit(false);
String str0 = "UPDATE ibk SET money = money-50000 WHERE sname='홍길동'";
String str1 = "UPDATE kb SET money = money+50000 WHERE sname='홍길동'";
stmt.addBatch(str0);
stmt.addBatch(str1);
//7.실행
int[] counts = stmt.executeBatch(); //각각의 sql문이 몇개행에 적용되었는지
isCommit = true; //커밋이 완료되었다는 의미
con.commit(); //"commit" sql문 실행
con.setAutoCommit(true); //수동커밋 -> 자동커밋 설정 변경
for (int i = 0; i < counts.length; i++) {
System.out.println(""+ (i+1) + " 명령" + counts[i] + "행 적용"); //배열 개수
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
// 전체 5개 sql문이 정상실행되지 않으면 모두 롤백(취소) 처리 한다.
try {
if(!isCommit) con.rollback(); //true가 아니면 롤백해라. 문장 실행 중에 하나라도 문제가 생기면 catch를 거쳐 finally로 가서 rollback을 해버린다.
//아래 부분은 객체 생성이 된 객체들을 닫기 처리한다.
if(stmt != null) stmt.close();
if(con != null) con.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
update문을 에러가 나도록 바꿔보았다.
package ex02.jdbcp.batchquery;
import java.sql.*;
public class BatchInsertEx {
static {
try {
Class.forName("oracle.jdbc.driver.OracleDriver");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
// 2. url, id, pass
String url = "jdbc:oracle:thin:@localhost:1521:xe";
String id = "bitTest";
String pass = "bitTest";
// 3. 관련 클래스 변수 선언
Connection con = null;
Statement stmt = null;
boolean isCommit = false; //커밋이 완료되었는지의 여부
try {
// 4. 오라클 서버 접속 객체 생성
con = DriverManager.getConnection(url, id, pass);
// 5. sql문 실행 객체 생성
stmt = con.createStatement();
// 6. 배치 쿼리 작성(한번에 여러개의 sql문을 작성하고 동시에 실행한다)
// 6.1 jdbc의 DML문 이후에 자동커밋 설정을 수동커밋으로 변경한다.
con.setAutoCommit(false);
String str0 = "UPDATE ibk SET money = money-50000 WHERE sname='홍길동'";
String str1 = "-UPDATE kb SET money = money+50000 WHERE sname='홍길동'";
stmt.addBatch(str0);
stmt.addBatch(str1);
//7.실행
int[] counts = stmt.executeBatch(); //여기서 에러가 발생. 밑으로 실행시키지 않는다.
isCommit = true;
con.commit();
con.setAutoCommit(true);
for (int i = 0; i < counts.length; i++) {
System.out.println(""+ (i+1) + " 명령" + counts[i] + "행 적용");
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
// 전체 5개 sql문이 정상실행되지 않으면 모두 롤백(취소) 처리 한다.
try {
//if(isCommit==false)와 같은 말
if(!isCommit) { //그러므로 isCommit은 아직 false, !isCommit은 if(true)가 되어 롤백 실행.
con.rollback();
System.out.println("원상태로 롤백하였습니다!!!");
}
//아래 부분은 객체 생성이 된 객체들을 닫기 처리한다.
if(stmt != null) stmt.close();
if(con != null) con.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}