2022-11-12 JDBC 정리, 복습하기
1. 드라이버 로딩
java.lang패키지의 Class라는 클래스의 forName이라는 메소드를 이용해서 오라클 드라이버의 핵심클래스를 메모리에 로딩
Class.forName("oracle.jdbc.driver.OracleDriver");
2. DB서버에 연결하기
=> java.sql패키지의 API를 이용
DriverManeger의 getConnection메소드를 이용해서 DB서버에 연결
1) static메소드이므로 클래스 이름으로 엑세스
static {
Class.forName("oracle.jdbc.driver.OracleDriver");
}
2) throws하고 있는 SQLException은 Exception클래스의 하위 클래스이르모 문법적으로 Exception처리를 해야 한다.
static { // DBUtil이 시작되는 순간 실행됨
try {
Class.forName("oracle.jdbc.driver.OracleDriver");
} catch(ClassNotFoundException e) {
e.printStackTrace();
}
}
3) 매개변수
① url : 연결문자열
② user : 사용자계정(scott)
③ password : 패스워드(scott계정의 패스워드:tiger1234)
String url = "jdbc:oracle:thin:@172.30.1.37:1521:xe";
String user = "scott";
String password = "tiger1234";
4) 리턴타입
: java.sql.Connection을 리턴
DriverManager클래스의 getConnection메소드는 DB서버에 연결하고 연결정보를 객체로 만들어서 리턴
Connection con = DriverManager.getConnection(url, user, password);
3. SQL문 실행 기능이 제공되는 객체를 생성
Connection객체에 정의되어 있는 preparedStatement메소드를 이용해서 생성
- sql문을 미리 파싱하는 방법이므로 Connection객체의 preparedStatement메소드를 이용해서 PreparedStatement객체를 만들 때 sql문을 전달해야 한다.
PreparedStatement ptmt = con.preparedStatement(sql);
- sql문을 작성할 때도 외부에서 입력 받아 처리할 부분은 ?로 대체하여 표시한 후 작업한다. ?에 대한 값을 셋팅해준다.
setXXX메소드는 타입과 연결해서 알맞은 setter메소드를 선택해서 작업(ResultSet의 getter메소드와 타입매칭은 동일)
ptmt.setString(1, "jang")
ptmt.setInt(2, 1000)
- 공통된 코드 추출해서 메소드로 만들어 작성하기
public class DBUtil {
//1. 드라이버 로딩
static { // DBUtil이 시작되는 순간 실행됨
try {
Class.forName("oracle.jdbc.driver.OracleDriver");
} catch(ClassNotFoundException e) {
e.printStackTrace();
}
}
// 2. DB서버 연결 - DB서버에 연결하고 커넥션객체를 리턴
public static Connection getConnect() {
Connection con = null;
String url = "jdbc:oracle:thin:@172.30.1.37:1521:xe";
String user = "scott";
String password = "tiger1234";
try { //getConnection메소드를 예외처리 해줘야 함
con = DriverManager.getConnection(url, user, password);
}catch(SQLException e) {
e.printStackTrace();
}
return con;
}
====>
Connection con = DBUtil.getConnect();
---------------------------------------- 지금까지 정리한 내용 순서대로 작성하기 --------------------------------------
public class test{
public int test{
String sql = "실행할 SQL문";
Connection con = null;
PreparedStatement ptmt = null;
try {
con = DBUtil.getConnect(); // 1. 드라이버 로딩
ptmt = con.prepareStatement(sql); //2. DB서버와 연결
ptmt.setString(1, id); //3. 값 세팅하기
ptmt.setString(2, pass);
ptmt.setString(3, "jang")
} catch (SQLException e) {
e.printStackTrace();
}
}
}
4. SQL문 실행하기
PreparedStatement를 사용. Statement메소드와 동일하게 동작하지만 PreparedStatement는 매개변수가 없다.
① executeUpdate
- insert, delete, update 명령문을 실행
- 매개변수에 전달된 sql문이 실행됨
- 실행결과로 몇 개의 row가 반영되었는지 리턴
=> int result = stmt.executeUpdate(sql)
-------------
ㄴ> 몇 개의 행이 삽입, 수정, 삭제되었는지 리턴
ex) if(result > 0) { sysout~~ } else { sysout~~ }
② executeQuery
- select명령문을 실행
- 실행한 후 조회된 테이블을 리턴, DBMS에서 조회된 테이블을 자바에서 사용하기 위해서 만들어놓은 객체가 ResultSet이다.
- 실제로는 어떤 DBMS가 사용되었는지에 따라서 다른 ResultSet객체(ResultSet의 하위)가 리턴
ptmt.executeUpdate();
ptmt.executeQuery();
// 매개변수X
5. 결과처리
1) insert, delete, update
- 모두 int를 리턴하므로 동일한 방법으로 처리
ex) int result = stmt.executeUpdate(sql)
2) select
- ResultSet 이용
- sql-plus프로그램을 이용해서 select sql문을 실행할 때 결과로 보여지는 2차원 표의 데이터를 자바에서 사용할 수 있도록 만들어 놓은 객체가 ResultSet이다.
- select문을 실행하면 ResultSet을 리턴하므로 ResultSet타입의 변수를 선언해서 결과를 참조
ResultSet rs = stmt.ececuteQuery(sql문)
ResultSet rs = ptmt.executeQuery() <- PreparedStatement는 변수X
- ResultSet에 있는 테이블의 데이터를 읽기 위해 ResultSet이 제공하는 메소드를 이용해서 작업
Cursor를 다음 레코드로 이동하면서 레코드 갯수만큼 반복작업을 수행
ResultSet객체의 next()메소드를 이용하여 다음레코드로 커서를 이동. next()는 커서를 이동했을 때 레코드가 존재하면 true를 리턴하고 없으면 false를 리턴
while(rs.nest()) { ---> true/false를 리턴하므로 반복문 중 while문을 이용하여 작업
// 레코드의 각 컬럼을 읽는다.
}
if(rs.next()){ //레코드 조회
System.out.print("성공");
}else {
System.out.println("실패");
}
}
- 한 번에 하나의 컬럼만 읽을 수 있다.
ResultSet객체의 getXXX메소드를 이용하여 컬럼값을 읽는다. 타입에 따라 다른 메소드를 이용한다.
① 오라클타입이 varchar2나 char인 경우 : java의 String
getString(컬럼명) or getString(컬럼순서 index)
② 오라클 타입이 number : java의 int
getInt(컬럼명) or getInt(컬럼순서 index)
③ 오라클 타입이 date : java의 Date
getDate(컬럼명) or getDate(컬럼순서 index)
while(rs.next()) { -> 커서를 하나씩 다음레코드로 이동해라
// 조회된 레코드 갯수만큼 반복해서 작업
sysout(rs.getString("name")) -> name이라는 컬럼명으로 정의된 컬럼을 조회
sysout(rs.getString(3)) -> 조회된 테이블의 3번째 컬럼을 조회
}
6. 자원반납
- 클라이언트가 점유해서 사용하던 자원을 반납해야 한다.
- Connection, Statement, ResulrtSet까지 모든 자원을 반납
- close메소드를 이용해서 처리
- 만들어진 순서가 아니라 제일 마지막에 생서된 객체부터 반납한다.
public static void close(ResultSet rs, Statement stmt, Connection con) {
try {
if(rs!=null)rs.close();
if(stmt!=null)stmt.close();
if(con!=null)con.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
---------------------------------------- 지금까지 정리한 내용 순서대로 작성하기 --------------------------------------
public ArrayList<CustomerDTO2> search(String job) { // 3. 직업으로 사원 검색
String sql = "select * from emp where job = 'ANALYST'";
ArrayList<CustomerDTO2> userlist = new ArrayList<CustomerDTO2>();
CustomerDTO2 user = null;
Connection con = null;
PreparedStatement ptmt = null;
ResultSet rs = null;
try {
con = DBUtil.getConnect();
ptmt = con.prepareStatement(sql);
rs = ptmt.executeQuery();
System.out.println("조회된 ResultSet객체 : " + rs);
while (rs.next()) {
System.out.print(rs.getString("job") + "\t");
user = new CustomerDTO2(rs.getInt(1), rs.getString(2), rs.getString(3), rs.getInt(4), rs.getDate(5),
rs.getInt(6), rs.getInt(7), rs.getInt(8));
userlist.add(user);
}
System.out.println("리스트 사이즈 : " + userlist.size());
} catch (SQLException e) {
e.printStackTrace();
} finally {
DBUtil.close(rs, ptmt, con);
}
return userlist;
}
=> try문 안에 변수를 정의하면 멤버변수가 되기 때문에 밖에서 null로 초기화를 해준다.
sql문이 select처리를 하므로 CustomerDTO2타입을 리턴한다. CustomerDTO2타입 변수 user에 ResultSet으로 조회된 정보들을 순서대로 담고 CustomerDTO2타입의 ArrayList에 넣어 리턴해준다.