60_[jsp servlet]jdbc(java database connectivity)
JDBC(Java Database Connectivity)
- 자바 프로그램에서 DB에 일관된 방식으로 접근할 수 있도록 API를 제공하는 클래스의 집합
- 몇몇 클래스들과 인터페이스의 묶음
JDBC를 이용하여 데이터베이스에 연결하는 과정
1.JDBC 드라이버 로드
⬇️
2.데이터베이스와 연결: DriverManager.getConnection()으로 Connection 객체 얻어오기
⬇️
3.SQL문 실행 : (1) 실행 준비1 Statement ~=connection.createStatement() 혹은 PrefaredStatement ~=connection.prepareStatement(sql문을 의미하는 String)
(2)SELECT문은 Statement객체.executeQuery() 그 외: Statement 객체.updateQuery()
⬇️
4.데이터베이스와 연결 끊음
JDBC 드라이버 연결하기
이클립스에서 드라이버 연결을 위한 jar 파일 및 설정 준비하기
I. 이클립스-DB 연결 1)Data Source Explorer
2)Database Connections 우클릭-new 선택
3)New Connection Profile이 뜸(계정명, 비밀번호를 통해서 접속했던 것과 동일)
4)Oracle 선택후 name 변경하지 않아도 된 채 next 누르기
5)new Driver Definition누르기(상자 두 개가 겹쳐진 버튼)
6)oracle thin driver 11 클릭-jar List탭 클릭
7)ojdbc14.jar 지우기(clear all)-add jar-C:\oraclexe\app\oracle\product\11.2.0\server\jdbc\lib 경로에 접근-ojdbc6.jar 선택-열기-(x표시가 없어짐을 확인-)ok
8)service name을 xe 로 적기(Database service name)
- connection url을 보면 @server가 있는데 이는 어디에 접속할지를 나타내는 것! -밑에 host에 127.0.0.1(localhost)를 입력하면 @server도 127.0.0.1(localhost ip주소)로 바뀜 [이는 기존 url 중 localhost에 해당! 만약,나중에 다른 컴퓨터의 db에 접속하려면 host부분을 변경해주면 됨] ➕ C:\oraclexe\app\oracle\product\11.2.0\server\jdbc\lib [오라클이 설치된 경로] 에서 tnsname.ora를 확인하여 db이름에 대해서 연결된 포트번호 확인하기!(참고로 기본연결은 1521포트) -user name, password 모두 sqlplus에서 create user identified by로 생성한 계정으로 로그인 -save password 체크-test connection 누르기 -ping succeeded!가 뜨면 db와 이클립스가 연결된 것! -finish 누르기
9)JDBC 연결을 진행할 프로젝트에 우클릭-Build Path-Configure Build Path -Libraries- External Library-위에서 추가했던 경로 내의 ojdbc.jar 파일을 클릭-apply and close
▶️ Referenced Libraries 가 생길 것!
(JSP에서는 아래의 방법을 추천!!)
JDBC 사용을 위한 템플릿 만들어서 사용하기
- JDBC사용을 동일한 계정으로 접근하는 경우 등이라면, 템플릿을 만들어두고 접근하여 사용하는 것이 보다 효율적이다! 차근차근 접근해보자!
- 주의할 점은, 두 개의 작업이 진행되고 있었는 데 둘 중 하나라도 작업이 실패하면 바로 둘 다 취소할 수 있도록 commit과 rollback을 적용해주어야 한다!
- JDBC 드라이버를 등록하고, Connection 객체로 접속하기
//1.DB연결
public static Connection getConnection() {
try {
//1.드라이버 등록
Class.forName("oracle.jdbc.driver.OracleDriver");
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
//드라이버 등록 실패 알리기
System.out.println("[ERR]드라이버 등록 실패");
e.printStackTrace();
}
//2.DB연결 준비-url, 계정명, 비밀번호
String url="jdbc:oracle:thin:@localhost:1521:xe";
String id = "KH";
String pwd = "KH";
//3.Connection 객체로 DB 연결하기
Connection conn = null;
try {
conn = DriverManager.getConnection(url,id,pwd);
conn.setAutoCommit(false);//자동으로 commit하는 것을 막고
// 둘 중 하나라도 작업 실패 시 취소할 수 있도록 메서드를 만들어 개발자가
//관리할 수 있도록 하기!
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return conn;
}
먼저, JDBC 드라이버를 등록하기 위해서
Class.forName 메서드에 JDBC 드라이버를 의미하는 oracle.jdbc.driver.OracleDriver를 매개변수로 넣어준다!
그 다음에는
Connection 커넥션인스턴스=DriverManager.getConnection(url, uId, uPwd);
와 같이
jdbc 드라이버 타입 및 호스트, 포트번호, db이름 정보를 담은 url jdbc:oracle:thin:[hostname][:port]:dbname
계정명, 계정 비밀번호
로 커넥션 객체를 만들어 DB에 연결해준다!
- ResultSet, Statement, Connection 객체를 모두 닫아서 연결 해제하기!(오버로딩)
//2.DB연결 해제-오버로딩하여 statement와 resultSet, connection 모두 close
public static void close(Connection conn) {
try {
conn.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
System.out.println("[ERR]Connection Close Error!");
e.printStackTrace();
}
}
public static void close(Statement stat) {
try {
stat.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
System.out.println("[ERR]Statement Close Error");
e.printStackTrace();
}
}
public static void close(ResultSet rs) {
try {
rs.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
System.out.println("[ERR]ResultSet Close Error!");
e.printStackTrace();
}
}
템플릿을 이용해서 JDBC 드라이버 등록 후 DB 연결 후에 사용을 하였다면, 그 다음에는 DB 연결을 해제해주어야 한다! SELECT문을 사용했다면 ResultSet이 반환되므로, ResultSet도 닫아주어야 한다!
이를 오버로딩을 이용한다면 보다 효율적으로 사용할 수 있다!
- 둘 중 하나가 작업 문제가 생겼을 때를 위한 메서드1-commit()
//3.커밋(저장)
public static void commit(Connection conn) {
try {
conn.commit();
} catch (SQLException e) {
// TODO Auto-generated catch block
System.out.println("[ERR]Commit Error!");
e.printStackTrace();
}
}
- 앞서 언급했던 바와 같이, 동시에 작업되던 관계있는 작업 중 하나가 실패했을 때에는 저장되지 않도록 방지해야 한다!
- 그래서 위에서 커넥션을 만들때 커넥션객체에 대해서 setAutoCommit을 false로 설정했다!
- 지금 위에서는 JDBC 템플릿 클래스에서 사용가능한 commit을 작성해줌으로써, 이제는 개발자가 원하는 로직, 상황, 시점에서 커밋을 통해 데이터를 저장해줄 수 있다!
- 둘 중 하나가 작업 문제가 생겼을 때를 위한 메서드2-rollback()
//4.롤백(취소)
public static void rollback(Connection conn) {
try {
conn.rollback();
} catch (SQLException e) {
// TODO Auto-generated catch block
System.out.println("[ERR]Rollback Error!");
e.printStackTrace();
}
}
- 이번에는 앞서 설명한 것과 동일한 상황에서, 작업을 취소해줄 필요가 있을 때 사용하고자 기존의 rollback 메서드를 JDBC 템플릿 클래스에서 이용하여 작성하였다!
Statement, PreparedStatement
- SELECT, UPDATE, DELETE 사용에 따른 쿼리문 실행 메서드 종류
🌺 특히, SELECT문은 한 행 이상의 데이터가 ResultSet으로 반환되므로, 자바에서도 ResultSet 객체를 만들어서 결과를 저장해서 statement 객체와 활용해주어야 한다!!
Statement stat= conn.createStatement(); stat.executeQuery(쿼리문); 혹은 stat.executeUpdate(쿼리문);
🌺 ResultSet 객체는 실제 데이터가 저장된 영역 외에 BOF(Begin Of File)과 EOF(End Of File)이 존재한다!
🌹 BOF: 첫 행 이전의 레코드 Set ≠ 헤더
🌹 EOF: 마지막 행 이후의 레코드 Set
🌺 ResultSet 클래스 메서드
- 성공적으로 진행될 경우에만 true 반환!
ResultSet 객체로 결과를 반환받아왔다면, getXXX메서드로 데이터를 선택해서 저장할 수 있다!
XXX는 String, Int 등을 의미한다! getXXX메서드는
🌺getXXX(인덱스[1부터 시작])
🌺getXXX(“속성명”)
으로 값에 연결하여 사용할 수 있다!
- PreparedStatement
- 컬럼 갯수가 많은 경우 등에 바인딩변수인 ?를 이용하여 쿼리문에 속성을 기입하는 어려움을 해소 시켜줄 수 있는 방법!
- 대신, 바인딩 변수?에 setXXX로 값을 설정해주어야 한다!
- 바인딩 변수를 이용한 쿼리문 준비
String sql = "SELECT (?,?,?,?,?) FROM 테이블명";
- PreparedStatement 객체 생성
PreparedStatement pStat = 커넥션객체.prepareStatement(sql);
- 바인딩 변수로 지정된 매개 변수에 값 설정
pStat.setString(1,name);
pStat.setInt(2,Integer.valueOf(age));
- 쿼리문 실행 후 닫기
pStat.executeQuery(); 혹은 pStat.executeUpdate();
pStat.close();
정리해보자면, Statement와 PreparedStatement 의 usage는
Statement: sql문 없이 먼저 connection 객체로 statement 객체 생성 ▶️ statement 객체의 executeXXX메서드로 쿼리문 실행 ▶️ statement 객체 닫기
package statement;
import static common.JDBCTemplate.*;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class JDBCStatement {
public static void main(String args[]) {
//쿼리문 준비
String sql="SELECT ID AS 아이디, NAME AS 이름, AGE AS 나이, EMAIL AS 이메일 FROM MEMBER_TMP";
//1.JDBCTemplate을 이용한 DB 연결
//connection
Connection conn = getConnection();
//2.Statement 준비
Statement stat = null;
//ResultSet 준비
ResultSet rs =null;
try {
stat = conn.createStatement();
//3.sql문 실행
rs = stat.executeQuery(sql);
//4.실행결과를 한행씩 넘기면서 출력하기
while(rs.next()) {
StringBuilder sb = new StringBuilder("아이디: "+ rs.getString(1)+", 이름: "+
rs.getString(2)+", 나이: "+rs.getInt(3)+", 이메일: "+rs.getString(4));
System.out.println(sb.toString());
}
} catch (SQLException e) {
// TODO Auto-generated catch block
System.out.println("[ERR]Statement 생성 오류!");
e.printStackTrace();
}finally {
//닫기
close(rs);
close(stat);
close(conn);
}
}
}
PreparedStatement : sql문으로 connection객체를 기반으로 PreparedStatement 객체 생성 ▶️ 바인딩 변수 및 setXXX메서드로 쿼리문 마저 완성하기 ▶️ executeXXX메서드로 쿼리문 실행 후 닫기
package preparedStatement;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import static common.JDBCTemplate.*;
public class Prepared {
public static void main(String[] args) {
// TODO Auto-generated method stub
//1.sql문 입력해두기
String sql="SELECT * FROM MEMBER_TMP WHERE ID=? AND NAME=?";
//2.Connection, PreparedStatement, ResultSet 준비
Connection conn = null;
PreparedStatement stat= null;
ResultSet rs= null;
//3.DB연결하기
conn=getConnection();
//4.statement생성하기
try {
stat = conn.prepareStatement(sql);
//5.바인딩변수 ? 와 매칭시키기
stat.setString(1, "100");
stat.setString(2, "김길동");
//6.쿼리 실행하기
rs = stat.executeQuery();
while(rs.next()) {
StringBuilder sb = new StringBuilder("아이디: "+ rs.getString(1)+", 이름: "+
rs.getString(2)+", 나이: "+rs.getInt(3)+", 이메일: "+rs.getString(4));
System.out.println(sb.toString());
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
close(rs);
close(stat);
close(conn);
}
}
}
와 같이 처음에 Connection 객체에 sql문을 같이 넣어주는지, executeXXX메서드 내부에 쿼리문을 넣어주는지(넣으면 Statement, 아니라면 PreparedStatement)의 차이가 있다!