본문 바로가기

코딩 공부/Java

[Java] 17_DAO 패턴

DAO 패턴

#01. DAO 패턴의 이해

1) DAO(Data Access Object) 패턴

  • DAO 패턴은 표준 J2EE 디자인 패턴들 중 하나로서 다음과 같은 요소들이 있다.
    • DAO 인터페이스
    • DAO 인터페이스를 구현한 클래스
    • 데이터 전송 객체(Beans에 대한 객체)=DTO(Data Transform Object)
      • 여러가지 변수를 전송하기 위해 자바빈즈(여러가지 복합적인 것을 묶는 최소단위)를 사용한다.
  • 이 패턴을 사용하여 저수준의 데이터 엑세스와 고급 비지니스 로직을 분리 할 수 있다.

2) DAO 패턴 작성 과정

  • 처리할 데이터가 저장되기 위한 데이터 베이스 테이블의 구조를 JavaBeans로 표현한다.
    • 데이터의 입력, 수정, 삭제, 조회(단일, 다중)의 기능을 명시한 Interface를 정의한다.
      • Interface를 상속받는 클래스를 준비하고, Interface에서 명시하고 있는 메서드들을 재정의한다.
        • 재정의 된 메서드의 기능을 구현한다.

#02. DAOEx 프로젝트 구성

1) 사용할 클래스와 라이브러리

  1. study.java.daoex.model 패키지
    • 프로그램에서 사용할 데이터의 구조를 정의한다.
  2. study.java.daoex.dao 패키지
    • 데이터베이스에 대한 입출력 기능을 인터페이스 형태로 설계한다.
  3. study.java.daoex.dao.impl 패키지
    • 설계된 인터페이스를 상속하여 실제로 동작할 기능을 구현한다.

#03. JavaBeans 만들기

  1. 자바빈즈 생성
    • 데이터베이스의 값을 보고 변수를 만들어 자바빈즈를 만든다.
mysql> desc department;
+--------+-------------+------+-----+---------+----------------+
| Field  | Type        | Null | Key | Default | Extra          |
+--------+-------------+------+-----+---------+----------------+
| deptno | int(4)      | NO   | PRI | NULL    | auto_increment |
| dname  | varchar(16) | NO   |     | NULL    |                |
| loc    | varchar(10) | YES  |     | NULL    |                |
+--------+-------------+------+-----+---------+----------------+
package study.java.daoex.model;

/** department 테이블 구조에 맞춘 Java Beans 생성 */
// 자바빈즈 - 여러가지 복합적인 것을 사용하기 쉽게 묶는 최소 단위
public class Department {
    private int deptno;
    private String dname;
    private String loc;
    public Department(int deptno, String dname, String loc) {
        super();
        this.deptno = deptno;
        this.dname = dname;
        this.loc = loc;
    }
    public int getDeptno() {
        return deptno;
    }
    public void setDeptno(int deptno) {
        this.deptno = deptno;
    }
    public String getDname() {
        return dname;
    }
    public void setDname(String dname) {
        this.dname = dname;
    }
    public String getLoc() {
        return loc;
    }
    public void setLoc(String loc) {
        this.loc = loc;
    }
    @Override
    public String toString() {
        return "Department [deptno=" + deptno + ", dname=" + dname + ", loc=" + loc + "]";
    }
}

#04. DAO 패턴 구성 실습

  1. DAO로 구현해야하는 기능을 인터페이스로 정의한다.
import java.util.List;

import study.java.daoex.model.Department;

public interface DepartmentDao {
    /**
     * 데이터를 저장한다. (INSERT 구문을 실행)
     * @param params    저장할 값을 담고 있는 Department 클래스의 객체
     * @return int        저장된 행의 primary Key값
     */
    public int insert(Department params);

    /**
     * 데이터를 삭제한다. (DELETE 구문을 실행)
     * @param params    WHERE절 조건값으로 사용할 deptno
     * @return int        삭제된 데이터의 수
     */
    public int delete(int params);

    /**
     * 데이터를 갱신한다. (UPDATE 구문을 실행)
     * @param params    Department 클래스의 객체
     * @return int         수정된 데이터의 수
     */
    public int update(Department params);

    /**
     * 데이터 한 건을 조회한다. (WHERE절을 사용한 SELECT문을 실행)
     * @param params    WHERE절 조건값으로 사용할 deptno
     * @return Department 조회된 데이터를 포함한 객체
     */
    public Department selectOne(int params);

    /**
     * 데이터 목록을 조회한다. (SELECT를 사용한 전체 데이터 조회)
     * @return List     조회된 데이터를 포함한 컬렉션
     */
    public List<Department> select();
}
  1. 데이터 처리 단계 (Insert, Delete, Update, 하나만조회, 전체조회)
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;

import study.java.daoex.dao.DepartmentDao;
import study.java.daoex.model.Department;

public class DepartmentDaoImpl implements DepartmentDao{

    /** 데이터 베이스 접속 객체 */
    private Connection conn;

    /** 생성자를 통해서 데이터베이스 접속 객체를 전달 받는다.*/
    public DepartmentDaoImpl (Connection conn) {
        this.conn = conn;
    }



    // 메서드가 재정의되었으므로 먼저 리턴값부터 정리
    @Override
    public int insert(Department params) {
        int result = 0;

        /** 실행할 SQL구문 정의*/
        String sql = "INSERT INTO department (dname,loc) VALUES(?,?)";

        /** SQL 구문 실행하기 위한 객체*/
        // -->import java.sql.preparedStatement;
        PreparedStatement pstmt = null;
        // -->import java.sql.ResultSet;
        ResultSet rs = null;

        /** SQL 구문 처리하기*/

        try {
            // pstmt 객체 할당
            pstmt = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);

            // 템플릿에 데이터 설정
            pstmt.setString(1, params.getDname());
            pstmt.setString(2, params.getLoc());

            // SQL문 실행하기 --> 결과 행의 수를 리턴할 변수에 대입함
            pstmt.executeUpdate();

            // Primary Key 받기
            rs = pstmt.getGeneratedKeys();
            rs.next();
            result = rs.getInt(1);

        } catch (SQLException e) {
            System.out.println("MySQL SQL Fail : " + e.getMessage());
        } finally {
            if(rs != null) {
                // 객체 닫기
                try {
                    rs.close();
                } catch (Exception e) {}
            }
            if (pstmt != null) {
                // 객체 닫기
                try {
                    pstmt.close();
                } catch (SQLException e) {}
            }
        }

        return result;
    }

    @Override
    public int delete(int params) {
        int result = 0;

        /** 실행할 SQL 구문 정의 */
        String sql = "DELETE FROM department WHERE deptno=?";

        /** SQL 구문 실행하기 위한 객체 */
        // --> import java.sql.PreparedStatement;
        PreparedStatement pstmt = null;

        /** SQL 구문 처리하기 */
        try {
            // pstmt 객체 할당
            pstmt = conn.prepareStatement(sql);

            // 템플릿에 데이터 설정
            pstmt.setInt(1, params);

            // SQL문 실행하기 --> 결과 행의 수를 리턴할 변수에 대입함
              result = pstmt.executeUpdate();
        } catch (SQLException e) {
            System.out.println("MySQL SQL Fail : " + e.getMessage());
        } finally {
            if (pstmt != null) {
                // 객체 닫기
                try {
                    pstmt.close();
                } catch (SQLException e) {}
            }
        }

        return result;
    }

    @Override
    public int update(Department params) {
        int result = 0;

        /** 실행할 SQL 구문 정의 */
        String sql = "UPDATE department SET dname=?, loc=? WHERE deptno=?";

        /** SQL 구문 실행하기 위한 객체 */
        // --> import java.sql.PreparedStatement;
        PreparedStatement pstmt = null;

        /** SQL 구문 처리하기 */
        try {
            // pstmt 객체 할당
            pstmt = conn.prepareStatement(sql);

            // 템플릿에 데이터 설정
            pstmt.setString(1, params.getDname());
            pstmt.setString(2, params.getLoc());
            pstmt.setInt(3, params.getDeptno());

            // SQL문 실행하기 --> 결과 행의 수를 리턴할 변수에 대입함
              result = pstmt.executeUpdate();
        } catch (SQLException e) {
            System.out.println("MySQL SQL Fail : " + e.getMessage());
        } finally {
            if (pstmt != null) {
                // 객체 닫기
                try {
                    pstmt.close();
                } catch (SQLException e) {}
            }
        }
        return result;
    }

    @Override
    public Department selectOne(int params) {
        Department result = null;

        /** 실행할 SQL 구문 정의 */
        String sql = "SELECT deptno, dname, loc FROM department WHERE deptno=?";

        /** SQL 구문 실행하기 위한 객체 */
        // --> import java.sql.PreparedStatement
        PreparedStatement pstmt = null;
        // --> import java.sql.ResultSet;
        ResultSet rs = null;

        /** SQL 구문 처리하기 */
        try {
            pstmt = conn.prepareStatement(sql);

            // 템플릿에 데이터 설정
            pstmt.setInt(1, params);

            // SQL문 실행하기 --> 결과 행 리턴됨
            rs = pstmt.executeQuery();

            // 조회 결과의 첫 번째 줄로 이동
            boolean first = rs.next();

            if(first) {
                // SELECT절에 명시한 컬럼 이름을 사용하여 데이터 추출
                int deptno = rs.getInt("deptno");
                String dname = rs.getString("dname");
                String loc = rs.getString("loc");

                // 리턴할 객체에 조회한 값을 사용하여 객체를 할당한다.
                result = new Department(deptno, dname, loc);
            } else {
                System.out.println("조회 결과가 없습니다.");
            }
        } catch (SQLException e) {
            System.out.println("MySQL SQL Fail : " + e.getMessage());
        } finally {
            // 객체를 생성한 순서의 역순으로 객체를 닫는다.
            if ( rs != null) {
                try {
                    rs.close();
                } catch (SQLException e) { }
            }
            if ( pstmt != null) {
                try {
                    pstmt.close();
                } catch (SQLException e) { }
            }
        }
        return result;
    }

    @Override
    public List<Department> select() {
        List<Department> result = null;

        // 'department' 테이블에 데이터를 갱신하기 위한 SQL의 템플릿
        String sql = "SELECT deptno, dname, loc FROM department";

        /** SQL 구문 실행하기 위한 객체 */
        // --> import java.sql.PreparedStatement;
        PreparedStatement pstmt = null;
        // --> import java.sql.ResultSet;
        ResultSet rs = null;

        try {
            // pstmt 객체 할당
            pstmt = conn.prepareStatement(sql);

            // SELECT 구문을 실행한 후, 결과셋을 리턴받는다.
            rs = pstmt.executeQuery();

            /** SQL 결과를 컬렉션에 할당*/
            // SQL이 실행되므로 컬렉션을 할당한다.
            result = new ArrayList<Department>();

            // 한 줄씩 스캔하는 반복문 구성
            while (rs.next()) {
                int deptno = rs.getInt("deptno");
                String dname = rs.getString("dname");
                String loc = rs.getString("loc");

                Department item = new Department(deptno, dname, loc);
                result.add(item);
            }
        } catch (SQLException e) {
            System.out.println("MySQL SQL Fail : " + e.getMessage());
        } finally {
            // 객체를 생성한 순서의 역순으로 객체를 닫는다.
            if ( rs != null) {
                try {
                    rs.close();
                } catch (SQLException e) { }
            }
            if ( pstmt != null) {
                try {
                    pstmt.close();
                } catch (SQLException e) { }
            }
        }
        return result;
    }

}
  1. Insert
public class Main01 {
    public static void main(String[] args) {
        // 1) 데이터베이스 접속
        // --> import java.sql.Connection;
        // --> import study.java.helper.DBHelper;
        Connection conn = DBHelper.getInstance().open();

        if (conn == null) {
            System.out.println("데이터베이스 접속 실패");
            return;
        }

        // 2) INSERT를 수행할 데이터 생성
        // --> 사용되지 않는 값(deptno)는 0(int)이나 null(String)로 지정한다.
        Department model = new Department(0, "인터넷통신", "공학관");

        // 3) 데이터 저장
        DepartmentDao dao = new DepartmentDaoImpl(conn);
        int result = dao.insert(model);

        // 4) 결과 판별
        System.out.println(result+ "번 데이터 저장됨");

        // 5) DB 접속 해제
        DBHelper.getInstance().close();
    }
}
  1. Delete
public class Main02 {
    public static void main(String[] args) {
        // 1) 데이터베이스 접속
        Connection conn = DBHelper.getInstance().open();

        if ( conn == null) {
            System.out.println("데이터베이스 접속 실패");
            return;
        }

        // 2) 삭제할 데이터
        // --> Main01에서 출력된 값을 입력하세요.
        int target = 207;

        // 3) 501번 데이터 삭제
        DepartmentDao dao = new DepartmentDaoImpl(conn);
        int result = dao.delete(target);

        // 결과 판별
        System.out.println(result + "개의 데이터 삭제됨");

        DBHelper.getInstance().close();
    }
}
  1. Update
public class Main03 {
    public static void main(String[] args) {
        // 1) 데이터베이스 접속
        Connection conn = DBHelper.getInstance().open();

        if (conn == null) {
            System.out.println("데이터베이스 접속 실패");
            return;
        }

        // 2) UPDATE를 수행할 데이터 생성
        Department model = new Department(102, "인터넷통신학과", "7호관");

        // 3) 데이터 수정
        DepartmentDao dao = new DepartmentDaoImpl(conn);
        int result = dao.update(model);

        // 4) 결과 판별
        System.out.println(result + "개의 데이터 수정됨");

        // 5) DB 접속 해제
        DBHelper.getInstance().close();
    }
}
  1. Selectone
public class Main04 {
    public static void main(String[] args) {
        // 1) 데이터베이스 접속
                Connection conn = DBHelper.getInstance().open();

                if (conn == null) {
                    System.out.println("데이터베이스 접속 실패");
                    return;
                }

                // 2) 조회할 데이터
                int target = 101;

                // 3) 데이터 수정
                DepartmentDao dao = new DepartmentDaoImpl(conn);
                Department result = dao.selectOne(target);

                // 4) 결과 판별
                if (result == null) {
                    System.out.println("조회결과 없음");
                } else {
                    System.out.println(result.toString());
                }

                // 5) DB 접속 해제
                DBHelper.getInstance().close();
    }
}
  1. Select
public class Main05 {
    public static void main(String[] args) {
        // 1) 데이터베이스 접속
        Connection conn = DBHelper.getInstance().open();

        if (conn == null) {
            System.out.println("데이터베이스 접속 실패");
            return;
        }

        // 2) 데이터 목록 조회
        DepartmentDao dao = new DepartmentDaoImpl(conn);
        List<Department> result = dao.select();

        // 3) 결과 판별
        if (result == null) {
            System.out.println("조회결과 없음");
        } else {
            for (int i = 0; i < result.size(); i++) {
                Department item = result.get(i);
                System.out.println(item.toString());
            }
        }

        // 4) DB 접속 해제
        DBHelper.getInstance().close();
    }
}

결론

  1. Interface를 만드는 이유
    • 자신이 원하는 기능을 분류하기 위하여 인터페이스를 정의
    • 즉, 인터페이스는 구현하고자 하는 기능에 대한 설계도.
  2. 데이터베이스 = 자료를 저장하기 위한 저장소
    • 자료는 내용의 주제에 따라서 테이블이라는 공간에 저장,수정,삭제,조회 된다.
    • 즉, INSERT, UPDATE, DELETE, SELECT가 수행된다.
  3. JavaBeans의 역할
    • 하나의 테이블(주제)를 표현하고 실제 데이터를 저장한다.
    • 프로그램 안에서 데이터를 전달하는 역할을 하기 때문에 DTO(Data Transfer Object)라고 부르기도 한다.
  4. DAO 패턴
    • 하나의 테이블 안에서 이루어지는 INSERT, UPDATE, DELETE, SELECT 처리를 Java언어로 표현하기 위한 구현 패턴.
    • 패턴이라 함은 구현을 위한 순서가 정해져 있다는 의미.
    • 즉, Impl 클래스의 구현 과정을 잘 파악해 두는 것이 중요한다.

'코딩 공부 > Java' 카테고리의 다른 글

[Java] 15_클래스와 객체  (0) 2020.05.29
[Java] 18_MyBatis 설정하기  (0) 2020.05.12
[Java] 16_생성자  (0) 2020.05.08
[Java] 17_은닉성  (0) 2020.05.08
[Java] 14_재귀호출  (0) 2020.05.08