JDBC
- def: 자바 언어에서 Database에 접근할 수 있게 해주는 프로그래밍 API
JDBC 인터페이스는 JDBC 프로그램을 하기 위한 API들로서, SE에서 제공하는 java.sql패키지를 의미한다. JDBC API는 대부분 인터페이스이다.
// JDBC API 인터페이스 Connection, Statement, ResultSet 등 // 메서드 Connection : createStatement(), getMetaData() ... Statement: executeQuery(), executeUpdate() ... ResultSet: next(), getXXX() ...
이 인터페이스들은 대부분 몸체가 없으며 이 API들을 활용하려면 java.sql 인터페이스를 상속하여 메서드를 구현할 클래스 파일들이 필요하다. 이 파일들을 드라이버라고 한다.
JDBC API는 모든 DB서버에 대해 공통적이지만, 이를 구현할 클래스 파일인 드라이버는 DB서버마다 다르다. 오라클 DB 서버로 구현하는 예시는 아래와 같다.
package jdbcexam; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.Statement; public class VisitorList { public static void main(String[] args) throws Exception { // 드라이버 로딩 Class.forName("oracle.jdbc.driver.OracleDriver"); // DBMS 서버 접속 Connection conn = DriverManager.getConnection( "jdbc:oracle:thin:@localhost:1521:XE", "jdbctest", "jdbctest" ); System.out.println(conn.getClass().getName()); // Statement 객체 생성 Statement stmt = conn.createStatement(); String sql = "select name, writedate, memo from visitor"; // SQL문 실행 ResultSet rs = stmt.executeQuery(sql); while(rs.next()) { System.out.print(rs.getString("name")); System.out.print(rs.getString("writedate")); System.out.print(rs.getString("memo")); System.out.println(); } // 객체 해제 rs.close(); stmt.close(); conn.close(); } }
드라이버 로딩
Class.forName()
에 드라이버 인터페이스를 상속하고 있는 클래스이름과 패키지명을 정확히 명시하여 로딩.
DB서버와 연결
DriveManager
클래스의getConnection()
메소드 사용. 첫번째 인자에 접속할 서버의String url
, 두번째 세번째 인자는 DB서버 로그인 아이디와 비밀번호.연결이 성공하면 DB와 연결된 상태를
Connection
객체로 표현하여 반환한다.Statement
객체 생성자바프로그램에서 SQL문을 전송할 statement 객체 생성. Connection 객체가 제공하는
createStatement()
메서드 사용.SQL문 실행
statement의
executeQuery()
메서드를 통해 실행 결과를ResultSet
객체에 담는다.ResultSet
객체 내부에는 위치를 나타내는 개념인 커서(Cursor)가 있다.ResultSet
객체 메서드들은 커서의 위치를 이동시킨다.void afterLast() // 커서를 끝 빈행 위치로 이동시킨다. void beforeFirst() // 커서를 시작 빈행 위치로 이동시킨다. boolean next() // 커서 다음 레코드가 있는지 판단하여 boolean값을 반환하고 커서를 다음 레코드로 이동시킨다.
try and catch resource문으로 에러 처리
package jdbcexam; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.Statement; public class VisitorList4 { public static void main(String[] args) { try { Class.forName("oracle.jdbc.driver.OracleDriver"); } catch (ClassNotFoundException e) { e.printStackTrace(); } String sql = "select name, writedate, memo from visitor"; try( Connection conn = DriverManager.getConnection( "jdbc:oracle:thin:@localhost:1521:XE", "jdbctest", "jdbctest" ); Statement stmt = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE); ResultSet rs = stmt.executeQuery(sql); ) { if(rs.next()) { int count = 0; rs.beforeFirst( ); while(rs.next()) { System.out.print(rs.getString("name")); System.out.print(rs.getString("writedate")); System.out.print(rs.getString("memo")); count++; System.out.println(" " +count + "번째 행 출력 완료"); } } else { System.out.println("추출된 행 없음"); } } catch (Exception e) { System.err.println("오류발생 : " + e); } } }
변수 선언과 초기화를
try()
블럭 내에 수행하여close()
생략 가능. 그리고 만약 테이블 내부에 값이 있는지 확인하기 위해if(rs.next())
를 사용한다면, 그냥 확인용으로 사용함에도 불구하고 next()는 커서를 다음 위치로 이동시켜 버리기 때문에, 원래라면 출력되어야 할 첫째 행이 출력되지 않는 문제가 있다. 그래서 ResultSet의 메서드인beforeFirst()
를 호출하여 시작 빈행 위치로 커서를 이동시켜주어야 하는데, 다만executeQuery()
메서드를 통해 획득된 ResultSet 객체는 후방향 탐색만이 가능하도록 되어있다. 그래서 전방향으로 이동하라는 명령을 내리면 전방향 전용 결과 집합에 부적합한 작업이 수행되었습니다. 라는 에러가 뜬다. 이 때createStatement()
메서드 내에ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE
을 추가해주면 정상 수행된다.