티스토리 뷰
DriverManager
JDBC 드라이버를 이용해 데이터베이스와 커넥션을 만드는 역할을 합니다. DriverManager는 Class.forName() 메소드로 생성됩니다. forName() 메소드는 driver class를 찾지못할 경우 ClassNotFoundException라는 Chekced Exception을 발생시키므로 예외 처리를 해야합니다. DriverManager의 모든 메소드는 static이므로 반드시 객체를 생성시킬 필요는 없습니다. getConnection() 메서드로 Connection 인터페이스 구현객체를 생성합니다.
Connection 인터페이스
DriverManager가 Connection을 만들고 Connection 인터페이스가 구현된 클래스의 객체로 표현됩니다. SQL문장을 정의하고 실행시킬 수 있는 Statement 객체를 Connection을 통해 생성합니다.
Statement 인터페이스
Connection 클래스의 createStatement() 메소드로 얻을수 있습니다. statement객체의 executeQuery() 메소드를 호출하여 SQL 질의를 실행시킬 수 있습니다. Statement 객체는 단순 질의문을 사용할 경우에 좋으며 그 이유는 preparedStatement를 설명할때 이유를 함께 설명하겠습니다.
PreparedStatement 인터페이스
Statement와 마찬가지로 Connection 객체에서 얻을수 있으며 preparedStatement() 메소드를 통해서 객체를 생성합니다. PreparedStatement 객체는 Statement 객체와 다르게 SQL문장이 미리 컴파일됩니다. PreparedStatement 객체는 동일한 Query를 특정값만 바꾸어서 여러번 수행할 때 유용합니다.
Statement는 Query가 실행될 때 매번 데이터베이스에서 분석되어야하지만, PreparedStatement 객체는 한번 분석되면 재사용이 용이합니다.
ResultSet 인터페이스
Query문중 Select문의 결과물로 ResultSet을 반환합니다. ResultSet은 커서(cursor)를 가지고 있습니다. 커서로 특정 행에대한 참조를 조작할 수 있습니다.
first() | 커서를 첫 번째 행으로 옮깁니다. |
last() | 커서를 마지막 행으로 옮깁니다. |
beforeFirst() | 커서를 첫번째 행 이전으로 옮깁니다. |
afterLast() | 커서를 마지막 행 다음으로 옮깁니다. |
next() | 커서를 다음 행으로 옮깁니다. |
previous() | 커서를 이전 행으로 옮깁니다. |
JDBC API를 이용한 DB연결
자바 어플리케이션에서 DB를 사용할때는 각 데이터베이스에서 제공하는 JDBC API를 이용한다. DBMS는 자신에게 알맞은 JDBC 드라이버를 제공한다.
1.물리적인 드라이버 설치
JDBC 라이브러리를 이용해 DB에 연결하기 위해서는 JDBC 라이브러리를 프로젝트에 추가해야 DB에 연결할 수 있다.
2.드라이버 로딩
JDBC 라이브러리를 Class.forName() 메소드를 이용해 메모리에 업로드 한다.
//오라클
Class.forName("oracle.jdbc.driver.OracleDriver");
//MySQL
Class.forName("com.mysql.jdbc.Driver");
//MS SQL
Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
3. 커넥션 연결
성공적으로 메모리에 업로드했다면 DB를 어플리케이션과 연결해야 한다. 이를 커넥션(Connection)이라고 하며 커넥션 수행코드는 다음과 같다.
//oracle
Connection conn = DriverManager.getConnection("jdbc:oracle:thin:@아이피:port:SIDl", id , password);
//mysql
Connection conn = DriverManager.getConnection("jdbc:mysql:localhost:port/db", id, password);
4. 생성된 쿼리(SQL)을 전달
작성된 쿼리를 DB로 전달하는 기능을 수행하는 클래스는 Statement나 PreparedStatement 클래스를 사용한다.
// Driver Loading
Class.forName("com.mysql.jdbc.Driver");
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
try {
String jdbcUrl = "jdbc:mysql://localhost:3306/db?useUnicode=true&characterEncoding-utf8";
String id = "userid";
String password = "userpassword";
String query = "...";
conn = DriverManager.getConnection(jdbcUrl, id, password);
stmt = conn.createStatement();
rs = stmt.executeQuery(query);
while(rs.next()) {
...
rs.getString("NAME");
rs.getString("MEMBERID");
rs.getString("EMAIL");
...
}
} catch(SQLException e) {
e.printStackTrace();
} finally {
if(rs != null) rs.close();
if(stmt != null) stmt.close();
if(conn != null) conn.close();
}
Statement객체를 이용한 쿼리실행
Statement를 이용할때는 두가지 메서드를 사용할 수 있다.
ResultSet executeQuery(String query): SELECT 쿼리를 실행한다.
int executeUpdate(String query): INSERT, UPDATE, DELETE 쿼리를 실행한다.
...
String query = "update MEMBER set NAME " + name + " " + "where MEMBERID = '" + memberID + "'";
Statement stmt = conn.createStatement();
int updateCount = stmt.executeUpdate(query);
...
Statement.executeUpdate 는 변경한 레코드의 개수를 return한다.
ResultSet에서 데이터 읽어오기
executeQuery를 실행하면 SELECT 쿼리의 실행결과를 java.sql.ResultSet 객체에 담아서 리턴한다. ResultSet 객체는 next() 메서드를 제공한다. next()를 수행하면 읽어올 값이 있는지를 체크한다 마지막 데이터에 도달하면 false를 리턴하고 읽어올 값이 있다면 true를 리턴한다.
...
while(rs.next()) {
String name = rs.getString(1);
}
...
PreparedStatement를 이용한 쿼리 실행
PreparedStatement는 Statement와 동일한 기능을 제공하지만 다른점은 SQL 쿼리의 틀을 미리 만들어놓고 값을 나중에 지정한다는것이 다르다. PreparedStatement에 동적인 데이터를 사용하는 부분에는 ?를 입력해놓고 set메서드를 사용해서 필요한 값을지정한다.
...
PreapredStatement psmt = conn.preparedStatement("insert into MEMBER values(?, ?, ?, ?)");
psmt.setString(1, memberID);
psmt.setString(2, password);
psmt.setString(3, name);
psmt.setString(4, email);
psmt.executeUpdate();
...
PreparedStatement를 사용하는 이유?
SQLInjection 방어
String 에서 + 등을 사용해서 쿼리를 생성하게 되면 바인딩되는 변수도 SQL문장의 의미를 가질 수 있다. 하지만 set을 통해서 바인딩한 값은 set 메소드 내에서 걸러줘 SQL문장의 의미를 가질 수 없다.
캐시(cache)사용여부
- 쿼리 문장 분석
- 컴파일
- 실행
Statement를 사용하면 매번 1~3 단계를 거치게 되지만 PreapredStatement를 사용하면 데이터베이스가 쿼리를 캐시해서 실행계획등은 그대로 사용하고 동적인부분만 변경해 수행하기 때문에 DB에 훨씬 적은 부하를 준다.
reference
- java-projects/java-h2-jdbc-sqlinjection at master · lurutia/java-projects (github.com)
- H2 Database - JDBC Connection - Tutorialspoint
- [JAVA] PreparedStatement 와 Statement 차이점 알아보기 (tistory.com)
- 세상의 모든 기록 :: 자바 정적쿼리와 동적쿼리 - Statement, PreparedStatement (tistory.com)
Heather :: [Java기초] 02.JDBC사용하기(Statement와 PreparedStatement 차이점) (tistory.com) - [Comporison] PreparedStatement 와 Statement | 장인개발자를 꿈꾸는 :: 기록하는 공간 (tistory.com)
'프로그래밍 언어 > Java Programming' 카테고리의 다른 글
객체지향 프로그래밍 OOP 5대원칙 SOLID (0) | 2021.02.25 |
---|---|
파일 확장자 또는 파일명만 추출하기 (0) | 2020.06.05 |
JAVA 실행시간 측정 방법 (0) | 2016.11.19 |
JAVA 직렬화 (Serializable) (0) | 2016.11.16 |
Java FilterStream feat. BufferedStream (0) | 2016.10.22 |