---
title: "Java 정리 35"
date: "2019-01-04"
tags: ["Java"]
status: archived
verified: false
---

---

## JDBC 복습

* **Class** : JVM 외부의 클래스(Driver)를 객체로 만들어 JVM에 올려 놓는 일
* **DriverManager** : 로딩된 드라이버를 사용하여 DB와 연결한 후 연결객체를 반환하는 일
* **Connection** : 연결관리, Transaction 처리, 쿼리문 생성 객체 얻는일
* **Statement, PreparedStatement, CallableStatement** : 쿼리문을 실행하여 결과를 얻는 일
  * **Statement, PreparedStatement** : 쿼리 실행
  * **CallableStatement** : Procedure 실행
* **ResultSet** : cursor의 제어권을 받아 여러행을 조회

![01](/md/legacy-assets/java/35/01.webp)

1. 드라이버 로딩

```java
Class.forName("oracle.jdbc.OracleDriver");
```

2. 로딩된 드라이버를 사용 Connection 얻기 (세가지의 정보 필요, DB url, 계정정보)

```java
String url = "jdbc:oracle:thin:@ip:1521:orcl"; // oracle port : 1521, sid : orcl
String id = "scott";
String pw = "tiger";

// Connection는 autocommit이 기본설정되어 있음, setAutoCommit()로 설정가능
Connection con = DriverManager.getConnection(url, id, pw);
```

3. 쿼리문 생성객체 얻기

```java
Statement stmt = con.createStatement();
```

4. 쿼리문 수행 후 결과 얻기

```java
int deptno = 90;
String dname = "댄스부";
String loc = "구로구";
String sql = "insert into dept(deptno, dname, loc) values("+deptno+",'"+dname+"','"+loc+"')";
// oracle에서 문자열은 작은따옴표로 묶음

int cnt = stmt.executeUpdate(sql);
```

5. 연결 끊기 (뒤에서부터 연결을 끊는다)

```java
stmt.close();
con.close();
```

## CRUD (CREATE, READ, UPDATE, DELETE)

* **C** - CREATE, INSERT
* **R** - SELECT
* **U** - ALTER, GRANT, REVOKE, UPDATE
* **D** - DROP, DELETE, TRUNCATE


## 쿼리문 실행객체

![02](/md/legacy-assets/java/35/02.webp)

* **Statement**
  * **쿼리문을 모른다.**
    * 쿼리문이 실행될 때 쿼리문을 알게된다.
  * 실행할 때 마다 쿼리문이 매번 생성되어 실행된다.
  * **bind변수 없다.**
    * (비유)총을 조립해서 쏘는 것
  * **SQL Injection이 발생할 수 있다.**
  * 쿼리문이 적은 횟수(한번)로 실행될 때 적합
* **PreparedStatement**
  * **쿼리문을 안다.**
    * 객체가 얻어질 때부터 쿼리문을 앎
  * 쿼리문은 미리 생성되어있고 값만 넣어 실행한다.
  * **bind변수 존재**
    * (비유)조립된 총에서 탄창넣어 쏘는 것
  * **SQL Injection이 발생할 수 없다.**
  * 쿼리문이 반복실행될 때 적합
* **CallableStatement**



## Statement 사용법

* **Statement 얻기**

```java
Statement stmt = con.createStatement();
```

* **insert, update, delete**
  * insert는 1행 추가 또는 Exception
  * update, delete는 0~n개의 행이 변경되거나 삭제 또는 Exception

```java
int cnt = stmt.executeUpdate("sql");
```

* **select**

```java
String sql = "select deptno, dname, loc from cp_dept";

// SELECT를 실행하면 커서를 가진 incline View 생성 후 커서의 제어권을 ResultSet으로 반환
ResultSet rs = stmt.executeQuery(sql);

// ResultSet은 DB와 Java간 데이터 변환도 한다!(NUMBER(oracle) -> int(Java))
int deptno = 0;
String dname = "";
String loc = "";

while(rs.next) {
    // 컬럼인덱스로 조회(비권장)
    // 0번은 커서 컬럼, 1번부터 시작
    // System.out.println(rs.getInt(1)+"  "+rs.getString(2)+" "+rs.getString(3));
    
    // 컬럼명으로 조회(권장)
    deptno = rs.getInt("deptno");
    dname = rs.getString("dname");
    loc = rs.getString("loc");
}
```

![03](/md/legacy-assets/java/35/03.webp)

## cp_dept에 CRUD작업하는 예제

* method별 JDBC사용 반복 연습
  * 효율성보단 연습을 위한 예제

![04](/md/legacy-assets/java/35/04.webp)

* Quantum DB를 이용 dept를 컬럼 복사하여 cp_dept 테이블 생성
  * pk_cp_dept PRIMARY KEY 설정

```sql
CREATE TABLE cp_dept AS (SELECT * FROM dept WHERE 1=0);
ALTER TABLE cp_dept ADD CONSTRAINT pk_cp_dept PRIMARY KEY(deptno);
```

* **[CpDeptVO](https://github.com/younggeun0/SSangYoung/blob/master/dev/workspace/sistJavaStudy2/src/date190104/CpDeptVO.java), [OneCpDeptVO](https://github.com/younggeun0/SSangYoung/blob/master/dev/workspace/sistJavaStudy2/src/date190104/OneCpDeptVO.java)**  
  * 차이는 deptno 유무 차이
  * **저장되는 값이 하나라도 다르면 새로운 VO를 만든다.**
    * 개발자의 실수로 다른 값을 입력할 수도 있음(휴먼에러 방지용)
* **[UseStatementCRUD](https://github.com/younggeun0/SSangYoung/blob/master/dev/workspace/sistJavaStudy2/src/date190104/UseStatementCRUD.java)클래스는 DAO클래스**
  * **DAO(Data Access Object)**
  * DB에 관련된 업무를 처리하는 클래스
* 실행시키는 **[RunUseStatementCRUD](https://github.com/younggeun0/SSangYoung/blob/master/dev/workspace/sistJavaStudy2/src/date190104/RunUseStatementCRUD.java) 클래스**

![05](/md/legacy-assets/java/35/05.webp)
