Java Web9 - DTO, DAO
DAO DTO 패턴
데이터베이스 관련 작업을 수행하는 어플리케이션에서 대부분 사용되는 패턴이다. DB 작업을 처리하는 코드는 DAO 클래스 내의 메서드에서 모두 수행하고 DB 작업에 사용되는 데이터는 DTO 클래스 내의 멤버변수를 통해 관리한다.
DAO(Data Access Object, 데이터 접근 객체)
데이터베이스 작업에 필요한 코드만 따로 모아놓은 클래스다. 데이터베이스 연결 및 해제 작업과 각 SQL 구문을 실행하는 코드를 DAO 클래스 내의 각각의 메서드를 통해 기술해놓고 외부에서 호출하여 사용하도록 제공한다. XXXDAO 클래스명을 사용하여 정의한다. 주로, XXX 은 해당 데이터베이스 작업을 수행하는 테이블명을 사용한다. 예시) 회원 정보 member 테이블 관련 작업을 수행하는 DAO 클래스 = MemberDAO
DTO(Data Transfer Object, 데이터 전송 객체)
데이터베이스 작업에 필요한 데이터를 보관하는 클래스다. DAO 객체가 데이터베이스 작업을 수행하기 위해 사용할 데이터를 전달하거나, DAO 객체로부터 데이터 조회 후 리턴받을 때 변수를 통해 각각의 데이터 관리가 가능하지만 DTO 객체를 통해 여러 데이터를 하나의 객체로 관리하고 전송하는데 활용하여 데이터를 편하게 주고받을 수 있다.
데이터베이스 테이블 내의 각 컬럼에 대응하는 멤버변수와(private) 각 멤버변수에 접근하기 위한 Getter/Setter 메서드로 구성된다. 필요에 따라 생성자도 정의할 수 있으며, 기본 생성자는 관례적으로 무조건 포함한다. XXXDTO 클래스명을 사용하여 정의한다. 주로, XXX 은 해당 데이터베이스 작업을 수행하는 테이블명을 사용한다. 단, JSP 어플리케이션 개발 시에는 XXXDTO 클래스를 XXXBean 클래스 또는 XXXVO 클래스로 작성하기도 한다.
DTO 예시
public class StudentDTO {
private int idx;
private String name;
public int getIdx() {
return idx;
}
public void setIdx(int idx) {
this.idx = idx;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "StudentDTO [idx=" + idx + ", name=" + name + "]";
}
}
DAO 예시
public class JdbcUtil {
public static Connection getConnection() {
Connection con = null;
try {
Context initCtx = new InitialContext(); // NamingException
DataSource ds = (DataSource)initCtx.lookup("java:comp/env/jdbc/MySQL");
con = ds.getConnection(); // SQLException
} catch (NamingException e) {
System.out.println("커넥션풀 접근 실패 - getConnection()");
e.printStackTrace();
} catch (SQLException e) {
System.out.println("DB 연결 실패 - getConnection()");
e.printStackTrace();
}
return con;
}
public static void close(Connection con) {
try {
if(con != null) {
con.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
public static void close(PreparedStatement pstmt) {
try {
if(pstmt != null) {
pstmt.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
public static void close(ResultSet rs) {
try {
if(rs != null) {
rs.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
미리 정의해둔 jdbc유틸 클래스다. 커넥션 객체를 가져오는 getConnection()과 사용 후 자원을 반납하는 close()다.
CREATE
public class StudentDAO {
public int insertStudent(StudentDTO student) {
int insertCount = 0;
// 미리 만들어둔 dbcp로 커넥션 객체를 가져온다.
Connection con = JdbcUtil.getConnection();
PreparedStatement pstmt = null;
try {
String sql = "INSERT INTO student VALUES (?, ?)";
pstmt = con.prepareStatement(sql);
pstmt.setInt(1, student.getIdx());
pstmt.setString(2, student.getName());
insertCount = pstmt.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
} finally {
JdbcUtil.close(pstmt);
JdbcUtil.close(con);
}
return insertCount;
}
}
자원 반환은 객체 생성의 역순으로 해야 한다.
StudentDTO student = new StudentDTO();
student.setIdx(Integer.parseInt(request.getParameter("idx")));
student.setName(request.getParameter("name"));
StudentDAO dao = new StudentDAO();
int insertCount = dao.insertStudent(student);
READ
public class StudentDAO {
public List<StudentDTO> selectStudentList() {
List<StudentDTO> studentList = null;
Connection con = JdbcUtil.getConnection();
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
String sql = "SELECT * FROM student";
pstmt = con.prepareStatement(sql);
rs = pstmt.executeQuery();
studentList = new ArrayList<StudentDTO>();
while(rs.next()) {
StudentDTO student = new StudentDTO();
student.setIdx(rs.getInt("idx"));
student.setName(rs.getString("name"));
studentList.add(student);
}
} catch (SQLException e) {
System.out.println("SQL 구문 오류 발생 - selectStudentList()");
e.printStackTrace();
} finally {
JdbcUtil.close(rs);
JdbcUtil.close(pstmt);
JdbcUtil.close(con);
}
return studentList;
}
}
StudentDAO dao = new StudentDAO();
List<StudentDTO> studentList = dao.selectStudentList();
for(StudentDTO student : studentList) {
...
}
UPDATE
public class StudentDAO {
public int updateStudent(StudentDTO student) {
int updateCount = 0;
Connection con = JdbcUtil.getConnection();
PreparedStatement pstmt = null;
try {
String sql = "UPDATE student SET name = ? WHERE idx = ?";
pstmt = con.prepareStatement(sql);
pstmt.setString(1, student.getName());
pstmt.setString(2, student.getIdx());
updateCount = pstmt.executeUpdate();
} catch (SQLException e) {
System.out.println("SQL 구문 오류 발생! - updateStudent()");
e.printStackTrace();
} finally {
JdbcUtil.close(pstmt);
JdbcUtil.close(con);
}
return updateCount;
}
}
StudentDTO student = new StudentDTO();
student.setIdx(Integer.parseInt(request.getParameter("idx")));
student.setName(request.getParameter("name"));
StudentDAO dao = new StudentDAO();
int updateCount = dao.updateStudent(student);
DELETE
public class StudentDAO {
public int deleteStudent(int idx) {
int deleteCount = 0;
Connection con = JdbcUtil.getConnection();
PreparedStatement pstmt = null;
try {
String sql = "DELETE FROM student WHERE idx = ?";
pstmt = con.prepareStatement(sql);
pstmt.setString(1, idx);
deleteCount = pstmt.executeUpdate();
} catch (SQLException e) {
System.out.println("SQL 구문 오류 발생! - deleteStudent()");
e.printStackTrace();
} finally {
JdbcUtil.close(pstmt);
JdbcUtil.close(con);
}
return deleteCount;
}
}
int idx = Integer.parseInt(request.getParameter("idx"));
StudentDAO dao = new StudentDAO();
int deleteCount = dao.deleteStudent(idx);
DTO를 반드시 사용해야만 하는 것은 아니고 주고 받는 데이터의 개수가 적다면 굳이 사용하지 않아도 된다. 상황에 따라 효율적인 판단을 하자.
Leave a comment