JDBC 작업 순서
*하기 순서에 입각하여 코딩해야 함*
*()은 항목 당 사용하는 Class/Interface명
1) 드라이버로딩 (Class)
2) Connection 얻기 (Connection, DriverManager)
3) 쿼리문 생성객체 얻기 (Statement, PreparedStatement, CallableStatement)
4) 쿼리문 수행 후 결과 얻기 (Select인 경우 ResultSet)
5) 연결 끊기
** 상세 과정 **
1. 드라이버 로딩
- DB Vendor사에서 제공 -> Oracle에서는 ojdbc8.jar
- new를 사용하지 않고 클래스를 JVM에 instance로 생성할 수 있는 클래스
- Class라는 Class (java.lang package)
- ClassNotFoundException 예외가 발생
- 문법) Class.forName(“드라이버클래스”);
Class.forName(“oracle.jdbc.OracleDriver”) // 클래스파일은 대소문자 구분 필수!!
2. Connection 얻기
- Connection Interface는 autocommit이 기본 설정이므로, java는 쿼리 실행 후 자동 commit이 됨
- 로딩된 드라이버를 관리하는 클래스 : java.sql package의 DriverManager Class
- 로딩된 드라이버를 사용하여 Connection URL(DB URL), id, password를 입력하고 DB와 연결된 connection을 얻음
- SQLException 예외 발생
- 문법) String url = “jdbc:oracle:thin:@DBServer위치:DB port:SID”; // "jdbc:oracle:thin:@localhost:1521:orcl";
String id = “아이디”; // scott
String pass = “비밀번호”; // tiger
Connection con = DriverManager.getConnection(url, id, pass);
① url
- 연결할 DB의 포트 번호와 DB명 넣어야 함
- @은 ip주소 표시하는 것, localhost(127.0.01.)는 loopback
- oracle은 1521가 기본 포트고, SID는 컴퓨터마다 유일한 하나의 값을 가짐!
② ip/pw
- 설정된 url에 id와 pw를 가지고 DB와 연동을 기다림
③ getConnection
- DB는 port를 열고 접속을 기다림 (오라클 port 번호 : 1521 / name : orcl)
> DB가 접속을 허가하면 인증 정보를 getConnection이 받는다
3. 쿼리문 생성객체 얻기
- 쿼리문 생성 객체 종류 : statement, preparedstatement, callablestatement
> Statement, PreparedStatement : 쿼리 실행
> CallableStatement : procedure 호출
- java.sql.Connection Interface로부터 얻음
- Statement
- 얻기 : Statement stmt = con.createStatement();
- 객체는 쿼리문을 실행할 때마다 반복적으로 계속 생성하여 실행하는 객체
> 쿼리문 실행 : excuteXXX(String sql)
- Statement 객체는 실행할 쿼리문을 알지 못함
- 쿼리문이 반복적으로 실행될 때 효율이 떨어짐
- 쿼리문에 값을 넣어 생성하기 때문에 쿼리문의 복잡도가 높음
- PreparedStatement / CallableStatement의 부모
- SQLInjection 발생 : injecton block code 작성 필요 - PreparedStatement
- 얻기 : PreparedStatement pstmt = con.prepareStatement(String sql);
> 쿼리문 실행 : excute()
- 객체는 쿼리문을 한 번만 생성하고 값만 넣어서 실행하는 객체
- PreparedStatement 객체는 실행할 쿼리문을 알고 있음
- 쿼리문에 bind변수를 설정하고 값을 나중에 입력함
> bind 변수 : 쿼리문 안에 ? 로 정의하는 변수, 추후에 값이 반드시 들어가야 함, PreparedStatment에서 많이 사용됨
- 쿼리문을 한 번만 생성하고 값을 변경하여 실행하기 때문에 쿼리문이 반복적으로 실행되는 환경에서 효율이 좋음
> Java는 대용량 서비스를 많이 제공하기 때문에 반복 쿼리가 많은 편이라 PreparedStatement가 자주 사용됨!
- 쿼리문과 입력되는 값을 따로 작성하기 때문에 쿼리문의 복잡도가 낮아짐
- Statement Interface의 하위 Interface이나, 부모의 method는 잘 쓰지 않음
- SQLInjection 발생하지 않음 : injecton block code 불필요 - CallableStatement
- 얻기 : CallableStatement cstmt = con.prepareCall(String sql);
> 여기서의 sql은 호출할 procedure명
- procedure를 호출하는 일 (직접 실행 - 쿼리문 없이 실행하는 것) // 쿼리는 간접 실행
- PreparedStatement Interface의 하위 Interface
- bind 변수로 입력하는 값을 할당할 수 있음
- registerOutParameter() method를 사용하여 procedure의 OutParameter를 처리해야 함
(OutParameter : java method의 반환형같은 것! OurParameter 여러 개 설정 가능)
4. 쿼리문 수행 후 결과 얻기
- 쿼리를 작성하여 실행
- 쿼리문 분류에 따라 사용하는 실행 method 가 다르므로 주의
(어떤 excute를 써도 실행은 되나, 올바른 결과가 아님)
- DB를 변경하는 쿼리문
create, drop, truncate, grant, revoke
- 처리 됐는지 안됐는지로 판단하므로, 반환형이 boolean인 Statement Interface의 execute() 사용
- stmt.excute()
insert, update, delete
- 몇 행이 추가/변경/삭제 되었는가가 중요하므로, 반환형이 int인 Statement Interface의 excuteUpdate() 사용
- 단, insert는 subquery가 아니라면 성공 아님 예외라서 return값을 안 받아도 됨
update와 delete : 0건 적용 (조건 잘못 넣었을때) or 적용완료 or 실패임
- stmt.excuteUpdate()
commit, rollback
- commit과 rollback은 Connection Interface에 method가 따로 존재하므로 그걸 씀
> commit(), rollback() - DB를 변경하지 않는 쿼리문
select
- 결과가 조회되어야 함! 반환형이 ResultSet인 Statment Interface의 excuteQuery() 사용
- ResultSet = stmt.excuteQuery() // ResultSet은 다음편에!
5. bind 변수에 값 설정 (PreparedStatment의 경우 해당)
- bind 변수는 쿼리문에 ?표로 기술하는 변수
- 장점) SQL문과 값이 분리된다
- PreparedStatement의 method 활용 (parameter index => bind index를 말함)
- bind 변수는 차례로 1번의 index부터 시작하며, setXXX()로 bind 변수에 값을 설정함
> 숫자 : pstmt.setInt (bind변수의 인덱스, 값);
> 문자열 : pstmt.setString (bind변수인덱스, 값);
- 주의)
① bind 변수에는 ‘ 를 사용하지 않음
② Java는 like 의 % 와 함께 사용되면 바인드 변수를 인식하지 못함
해결방법) where 컬럼명 like ‘?%’ (X)
=> %를 일반 문자열로 변경하고 ?와 붙여줌(‘와 || 사용)
=> where 컬럼명 like ?||’%’ (O)
③ bind 변수는 값이 들어가는 부분에만 사용할 수 있음 & 테이블명/컬럼명을 직접 사용할 수 없음
해결방법) 변수로 갖다 붙이자! "select * from ?" // 안됨=> "select * from " + 테이블명
> 단, 테이블명이 값으로 들어갈 때에는 bind변수를 사용할 수 있음 (다른 변수에 할당해서 사용은 가능)
6. 연결 끊기 (반드시!!)
- rs.close(); // select query의 경우 생성되는 ResultSet 객체가 있으면 이거 먼저 끊음
- stmt.close(); // Statement 객체 먼저 끊고
- con.close(); // 이후 Connection 끊기
'Development > JDBC' 카테고리의 다른 글
| [JDBC] DAO / PreparedStatement 활용 (0) | 2021.10.15 |
|---|---|
| [Java/JDBC] Singleton Pattern (0) | 2021.10.14 |
| [JDBC] SQL Exception / SQL Injection (0) | 2021.10.13 |
| [JDBC] ResultSet / Statement 활용 (0) | 2021.10.12 |
| [JDBC] JDBC / driver 종류 / java.sql package (0) | 2021.10.05 |