클라우드 융합 Full-stack 웹 개발자 양성과정/SQL, JDBC

SQL활용- OBJECT(VIEW, SEQUENCE), SQL응용 - JDBC(test, MVC패턴 실행순서, Statement 실행순서 )

thesunset 2022. 10. 5. 19:27

1. VIEW 뷰  

: SELECT(쿼리문)을 저장해둘 수 있는 객체

 (자주 쓰는 건 SELECT 문을 저장해두면 긴 SELECT문을 매번 다시 기술할 필요가 없음)

 임시테이블(실제 데이터가 들어가는 것은 아니다.)

 

- 한국에서 근무하는 사원들의 사번, 이름, 부서명, 급여, 근무국가명, 직급명 조회

 SELECT EMP_ID, EMP_NAME, DEPT_TITLE, SALARY, NATIONAL_NAME, JOB_NAME
 FROM NATIONAL
 JOIN LOCATION USING(NATIONAL_CODE)
 JOIN DEPARTMENT ON(LOCATION_ID = LOCAL_CODE)
 JOIN EMPLOYEE ON(DEPT_CODE = DEPT_ID)
 JOIN JOB USING(JOB_CODE)
 WHERE NATIONAL_NAME = '한국';

1) VIEW 생성방법

    [표현법]
  ①  CREATE VIEW 뷰명
              AS 서브쿼리;

  ② CREATE OR REPLACE VIEW 뷰명 
               AS 서브쿼리 

-> OR REPLACE는 생략이 가능함 

: 뷰 생성 시 기존에 중복된 이름의 뷰가 없다면 새로 만들고
    기존에 중복된 이름의 뷰가 있다면 해당 뷰를 변경(갱신)하는 옵션

-뷰 이름 : VW_EMPLOYEE

CREATE VIEW VW_EMPLOYEE
 AS  SELECT EMP_ID, EMP_NAME, DEPT_TITLE, SALARY, NATIONAL_NAME, JOB_NAME
        FROM NATIONAL
        JOIN LOCATION USING(NATIONAL_CODE)
        JOIN DEPARTMENT ON(LOCATION_ID = LOCAL_CODE)
        JOIN EMPLOYEE ON(DEPT_CODE = DEPT_ID)
        JOIN JOB USING(JOB_CODE);
--KH계정에 뷰 생성 권한이 없기 때문에 오류 발생

- 관리자계정 : 권한 부여 

GRANT CREATE VIEW TO KH;

- 다시 뷰를 생성절을 실행하면, 'View VW_EMPLOYEE이(가) 생성되었습니다.'라고 뜸.

SELECT * FROM VW_EMPLOYEE
WHERE NATIONAL_NAME = '한국';

SELECT * FROM VW_EMPLOYEE
WHERE DEPT_TITLE LIKE '해외%';

- > 따로 반복해서 적지 않아도 뷰명만 입력하면 조건 부여 가능 
- 뷰 생성 시 서브쿼리를 이용하면 그 때 그 때 알아보기 힘든 쿼리문을 길게 작성하는 것보다 한 번 만든 뷰를 통해서 편하게 조회가 가능하다. 

 

-만약 조회 싶은 컬럼을 추가하고 싶을 땐?

-> BONUS컬럼을 추가해보자.

CREATE OR REPLACE VIEW VW_EMPLOYEE
 AS  SELECT EMP_ID, EMP_NAME, DEPT_TITLE, SALARY, NATIONAL_NAME, JOB_NAME, BONUS 
        FROM NATIONAL
        JOIN LOCATION USING(NATIONAL_CODE)
        JOIN DEPARTMENT ON(LOCATION_ID = LOCAL_CODE)
        JOIN EMPLOYEE ON(DEPT_CODE = DEPT_ID)
        JOIN JOB USING(JOB_CODE);

OR REPLACE 옵션을 함께 쓰면 원래있던 VIEW가 갱신됨. 

- 뷰는 논리적인 가상 테이블 즉, 하드디스크에 실질적으로 저장이 되지 않음.(=존재하지 않음)

  쿼리문이 테이블에  TEXT로 저장되어있음. 

- 해당 계정이 가지고 있는 VIEW들에 대한 내용을 조회하고자 한다면 데이터 딕셔너리 중 USER_VIEW를 조회하면 된다. 

-사원의 사번, 이름, 직급명, 성별, 근무년수

CREATE OR REPLACE VIEW VW_EMP_JOB
    AS SELECT EMP_ID, EMP_NAME, JOB_NAME, 
            DECODE(SUBSTR(EMP_NO, 8, 1), 1, '남', 2, '여') , 
            EXTRACT(YEAR FROM SYSDATE) - EXTRACT(YEAR FROM HIRE_DATE) 
          FROM EMPLOYEE
          JOIN JOB USING(JOB_CODE);
--별칭을 지정하지 않아서 문제 발생 -> 함수식과 연산식에는 반드시 앨리어스 붙여주기
--00998: must name this expression with a column alias

CREATE OR REPLACE VIEW VW_EMP_JOB
    AS SELECT EMP_ID, EMP_NAME, JOB_NAME, 
            DECODE(SUBSTR(EMP_NO, 8, 1), 1, '남', 2, '여') "성별", 
            EXTRACT(YEAR FROM SYSDATE) - EXTRACT(YEAR FROM HIRE_DATE) "근무년수"
          FROM EMPLOYEE
          JOIN JOB USING(JOB_CODE);

-근무년수에 따라 사원들 조회 

SELECT * FROM VW_EMP_JOB
WHERE 근무년수 >= 10;

- 뷰를 삭제해보면,

DROP VIEW VW_EMP_JOB;
--실제 데이터가 삭제되는 것이 아닌 TEXT만 사라짐

2-1)  뷰를 이용해서 DML(INSERT, UPDATE, DELETE) 사용하기

    뷰에 적용 => 실제 데이터가 담긴 베이스테이블에 적용이 된다. 

- JOB테이블 복사한 VIEW 생성

CREATE OR REPLACE VIEW VW_JOB
    AS SELECT * FROM JOB;

- 뷰에 INSERT

INSERT INTO VW_JOB
VALUES ('J8', '인턴');

SELECT * FROM JOB;

-논리적 테이블(VW_VIEW)에 INSERT했는데 물리적테이블(JOB)에도 INSERT됨

-JOB_CODE가 J8인 JOB_NAME을 알바로 UPDATE

UPDATE VW_JOB
    SET JOB_NAME = '알바'
    WHERE JOB_CODE = 'J8';

* 수행결과에 따른 차이점

- SELECT : Result Set

- DML(INSERT, UPDATE, DELETE) : N행이(가) 삽입/변경/삭제되었습니다.

DELETE FROM VW_JOB
WHERE JOB_CODE = 'J8';

-만약 없는 조건을 삭제할 경우 '0행 이(가) 삭제되었습니다.'라고 출력 

COMMIT;

-DML을 실행한 뒤에는 반드시 트랜잭션 처리를 해주어야 함(COMMIT혹은 ROLLBACK)

2-2) 뷰를 이용해 DML처리가 불가능한 경우 

    ①뷰에 정의되지 않은 컬럼을 조작하는 경우
    ② NOT NULL제약조건이 지정된 경우
    ③ 산술연산식 또는 함수를 통해서 정의되어있는 경우
    ④ 그룹함수 GROUP BY절이 포함된 경우
    ⑤ DINTINCT 구문이 포함된 경우
    ⑥ JOIN을 이용해서 여러 테이블을 매칭시켜놓을 경우

 ①뷰에 정의되지 않은 컬럼을 조작하는 경우

--VIEW 생성
CREATE OR REPLACE VIEW VW_JOB
    AS SELECT JOB_CODE FROM JOB;
    
SELECT * FROM VW_JOB; --컬럼 1개
--INSERT
INSERT INTO VW_JOB(JOB_CODE, JOB_NAME) VALUES ('J8', '인턴');
--JOB_NAME을 찾을 수 없음

--UPDATE 
UPDATE VW_JOB
    SET JOB_NAME = '인턴'
    WHERE JOB_CODE = 'J7';
--JOB_NAME을 찾을 수 없음

--DELETE
DELETE FROM VW_JOB
WHERE JOB_NAME = '인턴';
--JOB_CODE로는 가능

-현재 VW_JOB 뷰에 존재하지 않는 JOB_NAME컬럼에 값을 추가, 변경, 삭제하고자 하면 오류 발생

-SQL오류: ORA-00904: "JOB_NAME": invalid identifier

 ② NOT NULL제약조건이 지정된 경우

CREATE OR REPLACE VIEW VW_JOB
    AS SELECT JOB_NAME FROM JOB;
    
SELECT * FROM VW_JOB;

--INSERT
INSERT INTO VW_JOB VALUES('인턴'); --JOB테이블에 (NULL, '인턴')이 삽입되려고 했다. 하지만 JOB_CODE는 NOT NULL제약조건

--UPDATE
UPDATE VW_JOB 
    SET JOB_NAME = '알바'
    WHERE JOB_NAME = '사원';

SELECT * FROM JOB;
--가능(VIEW에 존재하는 컬럼)
UPDATE VW_JOB 
    SET JOB_CODE = NULL
    WHERE JOB_NAME = '알바';
--불가능(VIEW에 존재하지 않는 컬럼)

ROLLBACK;
--DELETE

DELETE FROM VW_JOB
    WHERE JOB_NAME = '사원';

-사용하고 있는 자식데이터가 존재한다면 삭제가 안됨

③ 산술연산식 또는 함수를 통해서 정의되어있는 경우

-사원의 사번, 사원명, 급여, 연봉에 대해서 조회하는 뷰

--VIEW생성
CREATE OR REPLACE VIEW VW_EMP_SAL
    AS SELECT EMP_ID, EMP_NAME, SALARY, SALARY*12 "연봉"
        FROM EMPLOYEE;
--INSERT
INSERT INTO VW_EMP_SAL VALUES(400, '이승철', 20000000, 240000000);
--산술연산을 통해 나온 결과값에는 입력 불가능
--UPDATE 
UPDATE VW_EMP_SAL
    SET 연봉 = 40000000
    WHERE EMP_ID = 200;
--가상의 컬럼(산술연산)엔 불가능 

UPDATE VW_EMP_SAL
    SET SALARY = 7800000
    WHERE EMP_ID = 200;
--실제 존재하는 컬럼엔 가능

DELETE FROM VW_EMP_SAL
    WHERE 연봉 = 72000000;
--조작하는 것이 아니기에 가능
    
ROLLBACK;

 ④ 그룹함수 GROUP BY절이 포함된 경우

-부서별 급여 합, 평균급여를 조회하는 경우

--VIEW생성
CREATE OR REPLACE VIEW VW_GROUPDEPT
    AS SELECT DEPT_CODE, SUM(SALARY) "급여합", ROUND(AVG(SALARY)) "평균급여"
        FROM EMPLOYEE
        GROUP BY DEPT_CODE;

SELECT * FROM VW_GROUPDEPT;

--INSERT
INSERT INTO VW_GROUPDEPT VALUES('D0', 80000000, 400000);

--UPDATE
UPDATE VW_GROUPDEPT
    SET 급여합 = 8000000
    WHERE DEPT_CODE = 'D1';

--DELETE
DELETE FROM VW_GROUPDEPT 
    WHERE DEPT_CODE = 'D1';
    
--GROUPBY절로 묶여있거나 그룹함수로 묶여있는 경우 DML불가능

⑤ DINTINCT 구문이 포함된 경우

--VIEW생성
CREATE OR REPLACE VIEW VW_DT_JOB
AS SELECT DISTINCT JOB_CODE FROM EMPLOYEE;

SELECT * FROM VW_DT_JOB;

--INSERT
INSERT INTO VW_DT_JOB VALUES('J8');
--중복값을 제거하기 때문에 어느 컬럼에 삽입/수정/삭제를 해야할 지 모호함
--따라서, UPDATE, DELETE도 안됨

 ⑥ JOIN을 이용해서 여러 테이블을 매칭시켜놓을 경우

--VIEW생성
CREATE OR REPLACE VIEW VW_JOINEMP
    AS SELECT EMP_ID, EMP_NAME, DEPT_TITLE
    FROM EMPLOYEE
    JOIN DEPARTMENT ON(DEPT_CODE = DEPT_ID);

SELECT * FROM VW_JOINEMP;

--INSERT
INSERT INTO VW_JOINEMP VALUES(999, '가나다', 'A부');
--둘 이상의 테이블이 JOIN되었기 때문에 불가능 

--UPDATE
UPDATE VW_JOINEMP 
    SET EMP_NAME = '서동일'
    WHERE EMP_ID = 200;
--EMPLOYEE테이블에만 업데이트하기 때문에 가능 
--DELETE 또한 불가능 
ROLLBACK;

3) VIEW옵션

    [상세 표현법]
    CREATE OR REPLACE FORCE/NOFRCE VIEW 뷰명
        AS 서브쿼리
        WITH CHECK OPTION
        WITH READ ONLY;

 

   ①OR REPLACE : 해당 뷰가 존재하지 않으면 새로 생성 / 존재하면 갱신시켜주는 옵션
   ②FORCE / NOFORCE
            - FORCE : 서브쿼리에 기술된 테이블이 존재하지 않아도 뷰가 생성
            - NOFORCE(기본값) : 서브쿼리에 기술된 테이블이 반드시 존재해야만 뷰가 생성
   ③ WITH CHECK OPTION : 서브쿼리에 조건절에 기술된 내용에 만족하는 값으로만 DML가능
                          조건에 부합하지 않는 값으로 수정하는 경우 오류가 발생
   ④WITE READ ONLY : 뷰에 대해서 조회만 가능(DML 수행불가)

 

①OR REPLACE : 앞 서 구문들 참고

②FORCE / NOFORCE

: 기억할 때 TIP, FORCE = '힘이 쎈'으로 기억하기.

--DEFAULT값 : NO FORCE
CREATE OR REPLACE /*NO FORCE*/ VIEW VW_TEST
    AS SELECT FORCE, NOFORCE
        FROM NIKE; --없는 테이블은 생성 X
--FORCE : 힘이세서 강제로 생성 가능         
CREATE OR REPLACE FORCE VIEW VW_TEST
    AS SELECT FORCE, NOFORCE
        FROM NIKE;        
-- 경고: 컴파일 오류와 함께 뷰가 생성되었습니다.

하지만, 실행해보면

SELECT * FROM VW_TEST;
--오류 발생

FORCE로 옵션을 지정하는 이유는 추후 바로 테이블을 생성할 때 지정함. 

CREATE TABLE NIKE(
FORCE NUMBER,
NOFORCE NUMBER
);

SELECT * FROM VW_TEST;
--테이블 생성 후 다시 조회하면 오류 발생 X

③ WITH CHECK OPTION

CREATE OR REPLACE VIEW VW_EMP
    AS SELECT * FROM EMPLOYEE
        WHERE SALARY >= 3000000
    WITH CHECK OPTION;

SELECT * FROM VW_EMP;

SALARY가 3,000,000원 이상인 사원만 VW_EMP에 저장한다는 CHECK OPTION을 지정함. 

UPDATE VW_EMP
    SET SALARY = 2999999
    WHERE EMP_NAME = '선동일';
--서브쿼리에 기술한 조건에 부합하지 않기 때문에 변경 불가

ROLLBACK;

④WITE READ ONLY

: 읽기 전용

CREATE OR REPLACE VIEW VW_EMPBONUS
    AS SELECT EMP_ID, EMP_NAME, BONUS
        FROM EMPLOYEE
        WHERE BONUS IS NOT NULL
    WITH READ ONLY;

SELECT * FROM VW_EMPBONUS;

DELETE FROM VW_EMPBONUS
WHERE EMP_ID = 213;

-> 읽기 전용이기에 삭제(DML) 불가

2. SEQUENCE 시퀀스

 자동으로 번호를 발생시켜주는 역할을 하는 객체,  정수값을 자동으로 순차적으로 생성해줌.

예) 회원번호, 사번, 게시글 번호 등등 채번할 때 사용

    INSERT INTO MEMBER VALUES(1, 'user01', 'pass01', ...);
    INSERT INTO MEMBER VALUES(2, 'user01', 'pass01', ...);
    INSERT INTO MEMBER VALUES(3, 'user01', 'pass01', ...);
    INSERT INTO MEMBER VALUES(4, 'user01', 'pass01', ...);
    ...
    INSERT INTO MEMBER VALUES(1453, 'user01', 'pass01', ...);
    -> 실수할 확률이 높아짐

 

1) 시퀀스 객체 생성구문

    - CREATE SEQUENCE 시퀀스명 
    - START WITE 시작 숫자 => 생략가능, 처음 발생시킬 시작값 지정
    - INCREMENT BY 증가값 => 생략가능, 몇 씩 증가시킬 건지 지정
    - MAXVALUE => 생략가능, 최대값 지정
    - MINVALUE => 생략가능, 최소값 지정
    - CYCLE / NOCYCLE => 생략가능, 값 순환여부
    - CACHE 바이트크기 / NOCACHE => 생략가능, 캐시메모리사용여부 기본값은 20Byte

 

* SEQUENCE CACHE MEMORY : 미리 발생할 값들을 생성해서 저장해두는 공간
                                                        매번 호출 할 때 새로 번호를 생성하는 것은 비효율적이니
                                                        캐시메모리공간에 미리 생성된 값들을 가져다 쓰게해서 속도를 높임.

 * 접두사, 접미사
    - 테이블명 : TB_
    - 뷰명 : VW_
    - 시퀀스 : SEQ_
    * 회사마다 기준이 다르기에 회사 기준 따르기

CREATE SEQUENCE SEQ_EMPNO
START WITH 300--시작값
INCREMENT BY 5 --증가값
MAXVALUE 310 --최대값
NOCYCLE --순환X
NOCACHE; --캐시 미사용

 

2) 시퀀스 사용구문

    시퀀스명.CURRVAL : 현재 시퀀스 값(마지막으로 성공적으로 발생된 NEXTVAL값)
    시퀀스명.NEXTVAL : 시퀀스 값을 증가시키고 증가된 시퀀스값
                        기존의 시퀀스 값에서 INCREMENT BY 값만큼 증가된 값
                        (시퀀스명.CURRVAL + INCREMENT BY 값)

SELECT SEQ_EMPNO.CURRVAL FROM DUAL;

-> NEXTVAL을 한 번이라도 수행하지 않는 이상 CURRVAL을 수행할 수 없음

SELECT * FROM USER_SEQUENCES;
-- LAST_NUMBER : 현재 상황에서 NEXTVAL을 실행할경우 예정 값

SELECT SEQ_EMPNO.NEXTVAL FROM DUAL;
​
SELECT SEQ_EMPNO.CURRVAL FROM DUAL; -- 300
SELECT SEQ_EMPNO.NEXTVAL FROM DUAL; -- 305
​
SELECT SEQ_EMPNO.NEXTVAL FROM DUAL; -- 310
​
SELECT SEQ_EMPNO.NEXTVAL FROM DUAL; -- MAXVALUE에 걸침
SELECT SEQ_EMPNO.CURRVAL FROM DUAL;

 

3) 시퀀스 변경

    [ 표현법 ]
    ALTER SEQUENCE 시퀀스명
    INCREMENT BY 증가값 => 생략가능, 몇 씩 증가시킬건지 지정
    MAXVALUE => 생략가능, 최대값 지정
    MINVALUE => 생략가능, 최소값 지정
    CYCLE / NOCYCLE => 생략가능, 값 순환여부
    CACHE 바이트크기/NOCACHE => 생략가능, 캐시메모리사용여부, 기본값은 20Byte
    * START WITH는 변경불가

ALTER SEQUENCE SEQ_EMPNO
INCREMENT BY 10
MAXVALUE 400;

SELECT SEQ_EMPNO.CURRVAL FROM DUAL; --310
SELECT SEQ_EMPNO.NEXTVAL FROM DUAL; --340

시퀀스를 이용해 EMP_ID를 생성해보면, 

CREATE SEQUENCE SEQ_EID
START WITH 300;

INSERT INTO EMPLOYEE(EMP_ID, EMP_NAME, EMP_NO, JOB_CODE, SAL_LEVEL)
VALUES(SEQ_EID.NEXTVAL, '시퀀스맨', '1231231232', 'J3', 'S3');

INSERT INTO EMPLOYEE(EMP_ID, EMP_NAME, EMP_NO, JOB_CODE, SAL_LEVEL)
VALUES(SEQ_EID.NEXTVAL, '시퀀스맨맨', '123123', 'J2', 'S4');

SELECT * FROM EMPLOYEE;

-> 자동으로 300부터 순번 매겨짐

 

3. JDBC

1) 도입-드라이버란?

사용자와 하드웨어를 연결시켜주는 것은 OS

하드웨어 사에서 드라이버 제공해주어 작동하게끔 해줌

 

JDBC에도 적용해보면,

 

애플리케이션과 연결해주는 것이 JDBC Driver

 

앞으로 반드시 기본적으로 해주어야 하는 설정 ** 

전 세계 공통인 UTF-8로 변경

< Oracle SQL Developer >

- 관리자계정에서  JDBC계정생성, 최소한의 권한 부여

CREATE USER JDBC IDENTIFIED BY JDBC;
GRANT CONNECT, RESOURCE TO JDBC;

- JDBC TEST용 테이블 생성

CREATE TABLE TEST(
    TNO NUMBER,
    TNAME VARCHAR2(20),
    TDATE DATE
);

 

< ECLIPSE >

 ①ojdbc6.jar 추가하기

- 프로젝트 선택 후 마우스 오른쪽 클릭 > Properties -> Java BuildPath -> Libraires -> Add External JARs
 * -> c:\dev\objdbc6.jar 선택 -> Apply -> Apply and Close

References Libraries에 ojdbc6 추가 된 것을 확인
 * 만약 하지 않을 시 ClassNotFoundException 발생

 

② DML실행해보기

- 사용자에게 값을 입력받아서 DBMS로 전달

ㄱ. 값 입력받기 

		Scanner sc = new Scanner(System.in);
		System.out.println("번호를 입력해주세요.>");
		int num = sc.nextInt();
		sc.nextLine();
		System.out.println("이름을 입력해주세요.>");
		String name = sc.nextLine();

ㄴ. JDBC필요한 변수 셋팅

		int result = 0;
		Connection conn = null;
		Statement stmt = null;
		//1단계 끝

ㄷ. 실행 SQL("완성형태"로 만들기)

String sql = "INSERT INTO TEST VALUES(1, '박혜*', SYSDATE)";
		String sql = "INSERT INTO TEST VALUES(" + num + ", '" +name + "', SYSDATE)";
        //2단계 끝

ㄹ. JDBC driver등록 

		try {
			Class.forName("oracle.jdbc.driver.OracleDriver");
			System.out.println("driver 등록 성공");

ㅁ. Connection 객체 생성

	//DB에 연결(url, 계정명, 비밀번호)
	conn = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:xe", "JDBC", "JDBC");
	System.out.println("Connection 객체생성");

ㅂ. Statement 객체 생성

stmt = conn.createStatement();
	System.out.println("Statement 객체생성");

ㅅ. SQL쿼리를 날려서 실행 후 결과받기(처리된 행 수) 

result = stmt.executeUpdate(sql);

//내가 실행할 SQL문이 DML문(INSERT UPDATE DELETE)일 경우
//-> stmt.executeUpdate("DML문") : int

ㅇ. 트랜잭션 처리

//성공했으면 COMMIT, 아니면 ROLLBACK
if(result > 0) { //성공했을 경우
	conn.commit();
} else { //실패했을 경우
	conn.rollback();
}

ㅈ. 자원반납

} catch (ClassNotFoundException e) {
			e.printStackTrace();
} catch (SQLException e) {
			e.printStackTrace();
} finally {
		try {
				stmt.close();
				conn.close();
		} catch (SQLException e) {
				e.printStackTrace();
}
			
		}

ㅊ. 결과 반환

if(result > 0 ) {
			System.out.println("insert 성공");
} else {
			System.out.println("insert 실패");
}

③ SELECT - 내 로컬 PC DBMS상에 JDBC계정에 TEST테이블에 모든 데이터 조회해보기

-> ResultSet (조회된 데이터들 행의 집합) 받기

-> ResultSet으로부터 데이터 뽑기 

ㄱ. 변수 셋팅 

Connection conn = null;
Statement stmt = null;
ResultSet rset = null;
//1단계 끝

ㄴ. 실행 SQL

String sql = "SELECT * FROM TEST";

ㄷ. JDBC Driver 등록

try {
	Class.forName("oracle.jdbc.driver.OracleDriver");

ㄹ. Connection 객체 생성

conn = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:xe", "JDBC", "JDBC");

ㅁ. Statement 객체 생성

stmt = conn.createStatement();

ㅂ. SQL문 전달해서 실행 후 결과 받기 

rset = stmt.executeQuery(sql);

//내가 실행할 SQL문이 SELECT문일 경우
//stmt.executeQuery("SELECT문") : ResultSet

ㅅ. rset.next() : 커서를 움직여주는 역할, 해당 행이 존재한다면 true / 없으면 false

- 조회값 출력

while(rset.next()) {
	int tNo = rset.getInt("TNO"); //오타났다면, "부적합한 열이름" 오류
	String tName = rset.getString("TNAME");
	Date tDate = rset.getDate("TDATE");
	System.out.println(tNo + ", " + tName + ", " + tDate);
			}

ㅇ. 예외처리와 자원반납

} catch (ClassNotFoundException e) {
		System.out.println("드라이버 오타날 경우의 오류");
		e.printStackTrace();
} catch (SQLException e) {
		System.out.println("커넥션 오류");
		e.printStackTrace();
} finally {
		try {
			rset.close();
			stmt.close();
			conn.close();
		} catch (SQLException e) {
		e.printStackTrace();
		}

 

4. MVC 패턴

1) Model : 데이터와 관련된 역할(데이터를 담는다거나 , DB에 접근해서 데이터 입출력) - vo, dao

2) View : 사용자가 보게될 시각적인 요소 / 화면(입력, 출력)

3) Controller: 사용자의 요청을 받아서 처리 후 응답화면을 지정하는 역할 

< 기본 원칙 > 

 *  View단에서만 출력문 (System.out.println)을 사용한다. 
 *  Model의 DAO(Data Access Object)에서만 DB에 직접적으로 접근 한 후 해당 SQL문을 실행한 결과를 받는다.

 

MVC

5. JDBC

1) JDBC의 역할

① Java코드를 통해 DB서버에 접속
② SQL문을 구성하고 DB서버에서 실행
③ DB서버에서 처리한 결과를 가져오기

2) JDBC 사용객체 

DriverManager

* JDBC드라이버를 통해서 커넥션을 만드는 역할
 * Class.forName()메소드를 통해 생성되며, 반드시 예외처리를 해줘야 함 
 * getConnection()을 호출해서 Connection객체를 반환

Connection 

 * 특정 데이터 원본과 연결된 객체 
 * Statement 객체를 생성할 때도 connection객체를 이용해야 함 

Statement

 * Connection객체에 의해 프로그램에 구현되는 일종의 메소드 집합
 * Connection클래스의 createStatement()를 호출하여 객체 생성
 * Statement객체로 SQL문을 String객체로 담아 인지값으로 전달하여 질의를 수행

④ResultSet

* SELECT문을 사용한 질의 성공 시 반환되는 객체 
 * SQL 질의에 해당하는 결과를 담고 있으며 '커서(cursor)'를 이용하여 특정행에 대한 참조를 조작

 

 

Statement