[DB] JDBC 프로그래밍 - VO 패턴 / DAO 패턴(0716)

왕감자·2024년 7월 16일

KB IT's Your Life

목록 보기
84/177

VO 패턴

VO 객체 (Value Object)

  • 특정 테이블의 한 행을 매핑하는 클래스
  • 테이블을 표현하는 클래스~! (테이블 ➔ 클래스)

ORM
(클래스 ➔ 테이블)

  • 클래스 정의 ➔ 테이블
  • 필드 ➔ 컬럼
  • 인스턴스 ➔ 한 행

UserVO.java

package org.scoula.jdbc_ex.domain;

// VO객체 만들기
@Data
@NoArgsConstructor // 기본 생성자
@AllArgsConstructor // 전체 생성자
public class UserVO {
    // 컬럼들..~
    private String id;
    private String password;
    private String name;
    private String role;
}

DAO 패턴

DAO 클래스 (Data Access Object)

  • 데이터베이스에 접근하여 실질적인 데이터베이스 연동 작업을 담당하는 클래스
  • 테이블이 대한 CRUD 연산 처리
  • 인터페이스 정의 후 구현 클래스 작성
  • 제일 많은 시간이 걸림

UserDao.java - 인터페이스

package org.scoula.jdbc_ex.dao;

public interface UserDao {
    // 회원 등록
    int create(UserVO user) throws SQLException;

    // 회원 목록 조회
    List<UserVO> getList() throws SQLException;

    // 회원 정보 조회
    Optional<UserVO> get(String id) throws SQLException;

    // 회원 수정
    int update(UserVO user) throws SQLException;

    // 회원 삭제
    int delete(String id) throws SQLException;
}

UserDaoImpl.java

public class UserDaoImpl implements UserDao{
    Connection conn = JDBCUtil.getConnection();

    // USERS 테이블 관련 SQL 명령어
    private String USER_LIST = "SELECT * FROM USERS"; // * : UserVO로 맵핑시켜야 함.~
    private String USER_GET = "SELECT * FROM USERS WHERE ID = ?";
    private String USER_INSERT = "INSERT INTO USERS VALUES (?, ?, ?, ?)";
    private String USER_UPDATE = "UPDATE USERS SET NAME = ?, ROLE = ? WHERE ID = ?";
    private String USER_DELETE = "DELETE FROM USERS WHERE ID = ?";

    // 회원 등록
    @Override
    public int create(UserVO user) throws SQLException {
        try (PreparedStatement pstmt = conn.prepareStatement(USER_INSERT)) {
            pstmt.setString(1, user.getId());
            pstmt.setString(2, user.getPassword());
            pstmt.setString(3, user.getName());
            pstmt.setString(4, user.getRole());
            return pstmt.executeUpdate();
        }
    }

    // 목록보기, 상세보기에서 이용함~
    private UserVO map(ResultSet rs) throws SQLException {
        UserVO user = new UserVO();
        user.setId(rs.getString("ID"));
        user.setPassword(rs.getString("PASSWORD"));
        user.setName(rs.getString("NAME"));
        user.setRole(rs.getString("ROLE"));
        return user; // VO 객체 리턴~
    }

    // 회원 목록 조회
    @Override
    public List<UserVO> getList() throws SQLException {
        // 데이터가 없으면 빈 리스트라도 리턴해야 함 - Null(x) -> 후속 작업으로 루프 돌려야 해서~
        List<UserVO> userList = new ArrayList<UserVO>();

        Connection conn = JDBCUtil.getConnection();
        try (PreparedStatement pstmt = conn.prepareStatement(USER_LIST);
            ResultSet rs = pstmt.executeQuery()) {
            while (rs.next()) {
                UserVO user = map(rs);
                userList.add(user);
            }
        }
        return userList;
    }

    // 회원 정보 조회
    @Override
    public Optional<UserVO> get(String id) throws SQLException {
        try (PreparedStatement pstmt = conn.prepareStatement(USER_GET)) {
            pstmt.setString(1, id);
            try (ResultSet rs = pstmt.executeQuery()) {
                if (rs.next()) {
                    return Optional.of(map(rs)); // UserVO, Optional 데이터가 있음
                }
            }
        }
        return Optional.empty(); // if문 벗어남..~ 데이터 없다,,~ Null~
        // Optional 데이터가 있는지 없는지 확신 x -> Optional.ofNullable(a);
    }

    // 회원 수정
    @Override
    public int update(UserVO user) throws SQLException {
        Connection conn = JDBCUtil.getConnection();
        try (PreparedStatement pstmt = conn.prepareStatement(USER_UPDATE)) {
            pstmt.setString(1, user.getId());
            pstmt.setString(2, user.getPassword());
            pstmt.setString(3, user.getName());
            pstmt.setString(4, user.getRole());
            return pstmt.executeUpdate();
        }
    }

    // USERS 테이블 관련 CRUD 메서드
    // 회원 삭제
    @Override
    public int delete(String id) throws SQLException {
        try (PreparedStatement pstmt = conn.prepareStatement(USER_DELETE)) {
            pstmt.setString(1, id);
            return pstmt.executeUpdate();
        }
    }
}

테스트

UserDaoImplTest.java

@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
class UserDaoImplTest {
    UserDao dao = new UserDaoImpl();

    @AfterAll // 테스트가 끝날 때마다 JDBC유틸 close
    static void tearDown() {
        JDBCUtil.close();
    }

    @Test
    @DisplayName("User 등록")
    @Order(1)
    void create() throws SQLException {
        UserVO user = new UserVO("gamza", "gamza123", "감자", "ADMIN");
        int count = dao.create(user);
        Assertions.assertEquals(1, count);
    }

    @Test
    @DisplayName("UserDao User 목록 추출")
    @Order(2)
    void getList() throws SQLException {
        List<UserVO> list = dao.getList();
        for (UserVO vo: list) {
            System.out.println(vo);
        }
    }

    @Test
    @DisplayName("특정 User 1건 추출")
    @Order(3)
    void get() throws SQLException {
        // orElseThrow : 데이터가 있으면 리턴, 없으면 예외 던지기
        UserVO user = dao.get("gamza").orElseThrow(NoSuchFieldError::new);
        // Null이 아니어야 한다~ 하지만 위에서 Null이면 이미 예외 던짐ㅋ 여기선 사실 필요 X
        Assertions.assertNotNull(user);
    }

    @Test
    @DisplayName("User 정보 수정")
    @Order(4)
    void update() throws SQLException {
        UserVO user = dao.get("gamza").orElseThrow(NoClassDefFoundError::new);
        user.setName("왕감자");
        int count = dao.update(user);
        Assertions.assertEquals(1, count);
    }

    @Test
    @DisplayName("User 삭제")
    @Order(5)
    void delete() throws SQLException {
        int count = dao.delete("gamza");
        Assertions.assertEquals(1, count);
    }
}

0개의 댓글