디자인 패턴 DAO Pattern 개념과 예제
DAO Pattern이란?
▶ 업무와 DBMS를 분리하기 위해 사용됩니다. 업무와 데이터 2계층을 분리하고, 서로 그 상태를 동일하게 유지(persistence) 할 수 있습니다.
먼저 jdbc를 사용하기 위한 라이브러리를 추가하겠습니다. 아래 링크에서 다운로드 하시면 됩니다.
https://github.com/xerial/sqlite-jdbc/releases
파일을 다운로드하고 import하기 편한 위치에 저장하시면 됩니다.
1. Libaries 추가 intellij 기준입니다. File -> Project Structure -> '+' 위에 파일을 추가해주고 ok를 눌러줍니다.
코드요약: 학생은 학교 사이트에 가입합니다. 이때 primary key는 DB에서 자동적으로 생성 증가하며, 학생은 이름과 나이만 입력합니다.
클래스 다이어그램과 코드를 살펴보겠습니다.
1. SchoolDAOImpl class -> interface를 이용해서 상속한 이유는 여러가지 DB를 사용할 수 있기 때문에 유연성을 위해서 오버라이딩합니다.
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
public class SchoolDAOImpl implements SchoolDAO{
private Connection connection;
private Statement statement;
private String DBName;
private String tableName;
private ResultSet rs;
public SchoolDAOImpl(String DBName, String tableName) throws SQLException {
this.DBName = DBName;
this.tableName = tableName;
connection= DriverManager.getConnection("jdbc:sqlite:"+DBName);
statement=connection.createStatement();
statement.executeUpdate("DROP TABLE IF EXISTS "+ tableName);
statement.executeUpdate("CREATE TABLE "+ tableName+" (ID INTEGER PRIMARY KEY AUTOINCREMENT, name text, age INTEGER)");
System.out.println(tableName+" 생성완료");
}
@Override
public void insert(Student student) throws SQLException {
String fmt = "INSERT INTO %s VALUES(%d ,'%s', %d)";
String query = String.format(fmt, tableName, student.getId(),student.getName(), student.getAge());
statement.execute(query);
}
@Override
public List<Student> findAll() {
ArrayList<Student> students = new ArrayList<Student>();
try {
rs = statement.executeQuery("SELECT * FROM " +
tableName);
while (rs.next()) {
students.add(new Student(rs.getInt("id"),
rs.getString("name"), rs.getInt("age")));
}
}
catch (SQLException e) { e.printStackTrace(); }
return students;
}
@Override
public Student findById(int id) {
Student student = null;
try {
String fmt = "SELECT * FROM %s WHERE id = %d";
String q = String.format(fmt, tableName, id);
rs = statement.executeQuery(q);
if (rs.next()) {
student = new Student(rs.getInt("id"),
rs.getString("name"), rs.getInt("age"));
}
}
catch (SQLException e) { e.printStackTrace(); }
return student;
}
@Override
public void update(int id, Student student) {
Student result = findById(id);
if (result != null) {
try {
String fmt = "UPDATE %s SET name = '%s' WHERE id = %d";
String q = String.format(fmt, tableName,
student.getName(),student.getId());
statement.execute(q);
}
catch (SQLException e) { e.printStackTrace(); }
}
}
@Override
public void delete(int id) {
try {
String fmt = "DELETE FROM %s WHERE id = %d";
String q = String.format(fmt, tableName, id);
statement.execute(q);
}
catch (SQLException e) { e.printStackTrace(); }
}
@Override
public void delete(Student p) {
delete(p.getId());
}
}
Connection 인터페이스
- 자바 응용 프로그램과 데이터베이스를 연결한 세션 유지및 쿼리 실행합니다.
- 쿼리를 실행시킬 수 있는 Statement나 PreparedStatement 등을 생성하는 Factory입니다.
- createStatement(): SQL 쿼리를 실행시킬 수 있는 Statement 인터페이스 객체를 생성합니다.
Statement 인터페이스
- SQL 쿼리를 데이터베이스에서 실행합니다.
- SELECT 쿼리를 실행시킬 때 ResultSet 인터페이스 객체를 생성하는 Factory입니다.
- executeQuery(String sql): SELECT 쿼리를 실행하고 ResultSet 객체를 반환
- executeUpdate(String sql): 주어진 sql 쿼리를 실행
- create, drop, insert, update, delete 등 실행 가능
ResultSet 인터페이스
- 테이블의 한 행(row)를 가리키는 커서(cursor)입니다.
- 커서는 첫 번째 행 이전을 가리킵니다. -> next()를 이용해서 데이터가 실제 있는지 확인해야 합니다.
- next(): 현재 위치에서 커서를 다음 행으로 이동(true/false 반환)
- getInt(int columnIndex), getInt(String columnName): 주어진 컬럼의 데이터를 정수 형태로 반환
- getString(int columnIndex), getString(String columnName): 주어진 컬럼의 데이터를 문자열 형태로 반환
2. Student class
public class Student {
private Integer id;
private String name;
private Integer age;
public Student(Integer id, String name, Integer age) {
this.id = id;
this.name = name;
this.age = age;
}
public Integer getId() {
return id;
}
public String getName() {
return name;
}
public Integer getAge() {
return age;
}
}
3. Main class
import java.sql.SQLException;
import java.util.List;
public class Main {
public static void main(String[] args) throws SQLException {
SchoolDAO schoolDAO = new SchoolDAOImpl("school.db", "student");
// 학생 2명 추가
schoolDAO.insert(new Student(1,"kim",10));
schoolDAO.insert(new Student(2,"lee",13));
// 학생 전체 출력
List<Student> result = schoolDAO.findAll();
for (Student student1: result){
System.out.println(student1.getId()+" "+student1.getName()+" "+student1.getAge());
}
// id가 1인 학생 찾기
Student student = schoolDAO.findById(1);
System.out.println(student.getId()+" "+student.getName()+" "+student.getAge());
// id가 1인 학생의 이름 변경
schoolDAO.update(1, new Student(1, "park",10));
// id가 1인 학생이 바꼈는지 확인
student = schoolDAO.findById(1);
System.out.println(student.getId()+" "+student.getName()+" "+student.getAge());
// id가 2인 학생 삭제
schoolDAO.delete(2);
// 학생 전체 출력
result = schoolDAO.findAll();
for (Student student1: result){
System.out.println(student.getId()+" "+student.getName()+" "+student.getAge());
}
}
}
원하는 바와 같이 출력되는 것을 볼 수 있습니다.
지금까지 업무와 데이터 2계층을 분리하고, 서로 그 상태를 동일하게 유지하는 DAO Pattern을 알아봤습니다. 감사합니다.
전체 코드는 아래에서 확인 가능합니다:)
https://github.com/rlaehdals/design-pattern
'Desing Pattern' 카테고리의 다른 글
디자인 패턴 [퍼사드 패턴] Facade Pattern 개념 예제 (0) | 2022.01.03 |
---|---|
디자인 패턴 [어댑터 패턴] Adapter Pattern 개념 예제 (0) | 2022.01.03 |
디자인 패턴 (싱글톤 패턴) Singleton Pattern 개념과 예제 (0) | 2021.12.31 |
디자인 패턴 Factory Pattern 개념과 예제 (0) | 2021.12.30 |
디자인 패턴 (데코레이터 패턴) Decorator Pattern 개념과 예제 (0) | 2021.12.30 |
댓글
이 글 공유하기
다른 글
-
디자인 패턴 [퍼사드 패턴] Facade Pattern 개념 예제
디자인 패턴 [퍼사드 패턴] Facade Pattern 개념 예제
2022.01.03 -
디자인 패턴 [어댑터 패턴] Adapter Pattern 개념 예제
디자인 패턴 [어댑터 패턴] Adapter Pattern 개념 예제
2022.01.03 -
디자인 패턴 (싱글톤 패턴) Singleton Pattern 개념과 예제
디자인 패턴 (싱글톤 패턴) Singleton Pattern 개념과 예제
2021.12.31 -
디자인 패턴 Factory Pattern 개념과 예제
디자인 패턴 Factory Pattern 개념과 예제
2021.12.30