본문 바로가기

수업 정리

25일차 수업 정리

 

**프로그래밍 언어에서 데이터베이스 사용

1. 사전 준비

    => 프로그래밍 언어와 데이터베이스 사이에서 통역의 역할을 수행할 드라이버 설치

        - 자바에서는 드라이버 파일을 build Path에 추가해 주어야 함

        - ojdbc6.jar 파일을 프로젝트에 복사, 파일을 마우스 오른쪽을 클릭, [build path] - [add to build path] 메뉴 실행

    => 데이터베이스 접속 정보를 알아야 함

        - url : 데이터베이스 서버 컴퓨터의 ip나 도메인, 포트번호, 데이터베이스명(오라클 : sid, service name)

        - userid passward : 데이터베이스 종류에 따라 없어도 되는 경우가 있음(Access, Sqlite3)

        - 192.168.0.200, 1521, xe  / user08:user08

2. java에서 데이터베이스 연동작업

  1) 드라이버 클래스를 로드

    - Class.forName(String driverClassName);

    - driverClassName은 데이터 베이스 종류마다 다름

    - 이 작업은 프로그램 내에서 처음 1회만 수행(static Class)

    - 오라클 : oracle.jdbc.driver.OracleDriver

  2) 데이터베이스 연결

    - Connect 연결변수 = DriverManager.getConnection(String url[, String userid, String passward]);

    => url은 데이터베이스 종류마다 다름

        (오라클 url - "jdbc:oracle:thin:@192.168.0.200:1521:xe" or "1521/service name", "user08", "user08")

    => 연결에 실패하면 예외 발생

    => 데이터베이스 서버가 사용가능한지, url은 정확한지, id, pw가 맞는 지 확인(catch구문에서 예외내역 확인)

  3) SQL 실행 객체 생성

    => PreparedStatement : SQL 실행

        - PreparedStatement 실행객체변수 = 연결변수.prepareStatement(String sql);

    => CallableStatement : Procedure 실행

 

    => SQL 작성시 값의 자리에는 ?를 사용하여 나중에 바인딩 가능

        - insert -> values

        - update -> set의 값, where에서 조건의 값의 자리

        - delete -> where의 조건의 값의 자리

        - select -> where having에서 조건의 값의 자리

        - 컬럼 명은 ?로 대체 불가

        => ?자리에 값을 바인딩 : set자료형(물음표 번호, 실제 데이터)

 

  4) SQL 실행

    => select : resultSet 결과 변수 = 실행객체변수.executeQuery();

    => 그외 : int 결과변수 = 실행객체 변수.executeUpdate();

    => select 구문은 실행결과가 순서대로 결과에 접근 할 수 있는 cursor가 리턴

    => 나머지 구문은 영향받은 행의 갯수가 리턴

  5) 실행 결과 사용

  6) 생성된 객체들의 연결을 해제

    - ResultSet.close()

    - PreparedStatement.close()

    - Connection close()

    => 클라이언트가 서버에 직접 접속시 정확하게 해야 하고, 클라이언트가 앱 서버를 통하여 접속하는 경우 크게 문제가 되지 않음

 

**DEPT 테이블에 대한 삽입과 삭제 작업

1. DEPT 테이블 구조

    => DEPTNO : 숫자 2자리

    => DNAME : 문자 14자리 - 한글 4

    => LOC : 문자 13자리 -한글 4

2. Java Project 생성

 

3. 드라이버 설치

    => ojdbc.jar 파일을 프로젝트에 복사

    => 복사한 파일을 선택하고 마우스 오른쪽을 클릭 [build Path] - [Add To Build Path]를 실행

 

4. main 메소드를 소유한 클래스를 만들고 데이터를 삽입하는 코드를 작성

    => 에러발생시 constraint 단어가 보이면, 유일해야하는 데이터중 중복이 있거나, not null 설정된 열에 데이터를

        생략하고 입력하거나, foreign key로 설정된 열에 참조할 테이블에 없는 데이터등을 확인

    => table or view does not exist : 테이블이 없는 경우

    => SQL 메시지가 보이면 SQL을 잘못 작성한 경우

    => 자료형이 맞지 않으면 Invalid 자료형으로 에러 메시지가 출력됨

 

5. 확인 : 데이터베이스 접속 프로그램에서 실행

    => 삽입한 데이터가 있는 지 확인

 

6. select 작업

    => PreparedStatement executeQuery 메소드로 수행

    => 결과는 ResultSet 타입

  1) ResultSet next()

    => 다음 데이터가 있으면 그 데이터를 가리키는 곳으로 이동하고 true를 리턴(없으면 false 리턴)

    => if(ResultSet.next() == true){ 조회된 데이터가 있는 것 }else{ 조회된 데이터가 없는 것 }

    => 여러행의 데이터라면 아래처럼 반복문을 이용해서 각각의 행에 접근 하는 것이 가능

    => while(ResultSet.next(){ 행단위 작업 }

  2) ResultSet get 메소드

    => 열의 값을 가져올때 사용하는 메소드

    => get자료형(열이름이나 select 구문의 열 인덱스)로 사용

    => getInt, getDouble, getString, getDate의 형태로 만들어져 있음

    => 모든 열의 값은 getString으로 가져오는 것이 가능

        - getInt("deptno") : deptno열의 값을 정수로 리턴

        - getInt(1) : 첫번째 열의 값을 정수로 리턴

        - getString("dname") : dname 열의 값을 문자열로 리턴

  3) main 메소드를 소유한 클래스를 만들고 main 메소드에 작성

    => DEPT 테이블의 전체 데이터를 읽어와서 출력

SELECT DEPTNO, DNAME, LOC
FROM DEPT;

  4) main 메소드를 만들고 작성

    => deptno(primary key - not null, unique)를 입력받아서 deptno에 해당하는 데이터를 조회(상세보기)

[가져오는 방법들]

select deptno, round(avg(sal)) 평균급여
from emp
group by deptno; 

rs.getInt("deptno")
rs.getInt("round(avg(sal))") => rs.getInt("평균급여") => rs.getInt(2)

7. Transaction

    => 한번에 처리되어야하는 작업의 단위

  1) 구현방식

    - auto-commit : sql문장이 성공적으로 수행되면 자동으로 commit - 자바의 기본

    - manual-commit : commit이나 rollback을 명시적으로 호출해야만 commit, rollback 되는 방식

  2) java에서의 활용

    => 기본은 AutoCommit인데, ManualCommit으로 변경하려면 Connection.setAutoCommit(false); 호출

    => Commit이나 Rollback을 하고자 하는 경우 Connection.commit() or rollback()을 호출

    => rollback은 작업을 취소하는 명령, 대부분의 경우 하나의 거래를 수행하는 도중 예외가 발생하면 rollback

    => 작업이 정상적으로 완료시, commit을 호출하여 원본에 작업 내용 반영

 

**Procedure 연동

1. PROCEDURE

    => 자주 사용하는 SQL문장을 하나의 이름으로 만들어 두고 프로그래밍 언어의 메소드처럼 사용하는 것

    => 사용자에게 실제 테이블의 구조를 보여주지 않아도 되서 보안이 향상 됨

    => SQL문장은 보조 기억장치에서 주기억장치로 불러와서 실행되지만 프로시저는 한번 컴파일되면 주기억장치에

       상주한 상태로 실행되기에 실행속도도 향상됨

    => 프로시저를 만드는 문법은 데이터베이스 종류에 따라 서로 다름

        - Oracle에서 프로시저 만드는 문법 : PL/SQL

    => DEPT 테이블에 데이터를 삽입하는 프로시저

CREATE OR REPLACE PROCEDURE INSERT_DEPT_PROC
(VDEPTNO IN DEPT.DEPTNO%TYPE,
VDNAME IN DEPT.DNAME%TYPE,
VLOC IN DEPT.LOC%TYPE)
IS
BEGIN
           INSERT INTO DEPT(DEPTNO, DNAME, LOC)
           VALUES(VDEPTNO, VDNAME, VLOC);
END;
/

    => 앞에서 만든 프로시저 테스트

BEGIN
           INSERT_DEPT_PROC(01, '기획', '서울');
END;

    => 프로시저는 SI업체와 같은 대기업, 공공기관 프로젝트를 받아서 하는 기업은 되도록 사용

    => Start-up이나 중소기업처럼 역할이 분리되지 않은 곳에서는 잘 사용하지 않음

 

2. Java에서 프로시저 사용

    => PreparedStatement 대신 CallableStatement 생성

        - CallableStatement 실행객체 변수 = Connection.prepareCall("{call 프로시저명(?...)}");

        - 실행객체 변수.set자료형(물음표 번호, 실제 데이터)...

    => 실행은 executeUpdate() 또는 executeQuery()

 

3. 앞에서 만든 insert_dept_proc

 

**데이터베이스 연동 패턴

1. DTO(Data Transfer Object - Variable Object, Domain) 패턴

    => 여러개의 속성을 묶어서 하나로 표현하기 위한 클래스를 DTO 또는 VO라고 함

    => 테이블과 매핑되는 클래스를 만들어서 사용하는 패턴

       (이패턴의 확장 : ORM(SQL없이 인스턴스만으로 데이터 베이스 작업을 수행하도록 해주는 프레임 워크))

2. DAO(Data Access Object)

    => 데이터베이스 작업만 수행하는 별도의 클래스를 만들어서 사용하는 패턴

    => 이 패턴을 서버에 적용할 때는 특별한 경우가 아니면 Singleton Pattern으로 디자인

3. Singleton

    => 객체를 하나만 만들수 있도록 클래스를 디자인하는 패턴

4. Service : 사용자의 요구(Business Logic)를 처리하는 클래스

5. Controller : 사용자의 요청을 받아서 필요한 Service를 호출하는 클래스

6. View : 클라이언트가 보고있는 화면

 

**DTO & DAO 패턴을 이용한 CRUD(Create Read Update Delete)작업

1. 작업에 필요한 샘플 데이터 생성

  1) 샘플 테이블 생성

    - 상품 테이블

    상품 코드 : 영문과 숫자로 이루어진 문자열 10자리 - 자주 변함 PRIMARY KEY

    상품 명 : 한글 포함한 20자리 문자열 - 변하지 않음, 필수

    상품 원산지 : 한글 포함한 50자리 문자열 - 변하지 않음, 필수

    상품 가격 : 정수 10자리 이내 - 기본값 0

    상품 입고일 : 날짜 - 기본값 오늘 날짜

ISBN : 영문과 숫자로 이루어진 문자열 20자리 - 변하지 않음 PRIMARY KEY
책 제목 : 한글 포함한 20자리 문자열 - 변하지 않음, 필수
출판사 : 한글 포함한 50자리 문자열 - 변하지 않음, 필수
책 가격 : 정수 10자리 이내 - 기본값 0
출간일 : 날짜 - 기본값 오늘 날짜 

CREATE TABLE BOOK(
           ISBN VARCHAR2(20) PRIMARY KEY,
           BOOKNAME VARCHAR2(60) NOT NULL,
           AUTHOR VARCHAR2(30) NOT NULL,
           COMPANY VARCHAR2(150) NOT NULL,
           PRICE NUMBER(10) DEFAULT 0,
           FIRSTDATE DATE DEFAULT SYSDATE); 

--샘플데이터 입력

INSERT INTO BOOK(ISBN, BOOKNAME, AUTHOR, COMPANY, PRICE, FIRSTDATE)
VALUES(001, '난중일기', '이순신', '지학사', 15000, SYSDATE-10);

INSERT INTO BOOK(ISBN, BOOKNAME, AUTHOR, COMPANY, PRICE, FIRSTDATE)
VALUES(002, '난장이가 쏘아올린 작은 공', '작자 미상', '아름다운나무', 7000, SYSDATE-30);

INSERT INTO BOOK(ISBN, BOOKNAME, AUTHOR, COMPANY, PRICE, FIRSTDATE)
VALUES(003, '셰익스피어 4대 비극', '셰익스피어', '청어람', 10000, SYSDATE-20);

INSERT INTO BOOK(ISBN, BOOKNAME, AUTHOR, COMPANY, PRICE, FIRSTDATE)
VALUES(004, '죄와벌', '도프토예프스키', '푸른숲', 15000, SYSDATE-1);

COMMIT;

2. 테이블의 데이터를 표현 할 클래스를 자바 프로젝트에 생성

public class Books {
           private String ISBN;
           private String bookName;
           private String author;
           private String company;
           private int price;
           private Date pubDate;          

           //생성자 - 인스턴스를 생성하기 위해서 호출하는 메소드
           //생성자는 new로 호출
           public Books() {
                     super();
                     // TODO Auto-generated constructor stub
           }          

           public Books(String iSBN, String bookName, String author, String company, int price, Date pubDate) {
                     super();
                     ISBN = iSBN;
                     this.bookName = bookName;
                     this.author = author;
                     this.company = company;
                     this.price = price;
                     this.pubDate = pubDate;
           }

           //접근자 메소드 - getters & setters
           public String getISBN() {
                     return ISBN;
           }
           public void setISBN(String iSBN) {
                     ISBN = iSBN;
           }

           public String getBookName() {
                     return bookName;
           }
           public void setBookName(String bookName) {
                     this.bookName = bookName;
           }

           public String getAuthor() {
                     return author;
           }
           public void setAuthor(String author) {
                     this.author = author;
           }

           public String getCompany() {
                     return company;
           }
           public void setCompany(String company) {
                     this.company = company;
           }

           public int getPrice() {
                     return price;
           }
           public void setPrice(int price) {
                     this.price = price;
           }

           public Date getPubDate() {
                     return pubDate;
           }
           public void setPubDate(Date pubDate) {
                     this.pubDate = pubDate;
           }

           //디버그를 빠르게 하기 위한 메소드
           @Override
           public String toString() {
                     return "Books [ISBN=" + ISBN + ", bookName=" + bookName + ", author=" + author + ", company=" + company
                                           + ", price=" + price + ", pubDate=" + pubDate + "]";
           }

 

3. DAO 클래스를 생성 - 데이터베이스 작업만을 담당하는 클래스

    => GoodDAO 클래스

    => 서버에서 사용할 것이라면 Singleton 패턴으로 작성