본문 바로가기
Java

[Java] DAO 클래스의 리팩토링(inser, update 쿼리)

by bkuk 2023. 3. 22.

너무나도 많은 중복이 발생하는 UserDao 클래스

 

개발자라면 누구나 한번쯤은 JDBC 라이브러리를 사용한 적이 있을 것이다. 주로 Dao 클래스에서 이를 사용한다.

데이터베이스 쿼리 하나를 실행하기 위해서 개발자가 구현해야 할 코드가 굉장히 많다. 구현할 코드가 각 쿼리마다 다른 부분이라 개발자가 구현할 수 밖에 없다면 모르겠지만 대부분의 구현은 매번 반복되는 부분이다.

반복적인 부분이 있는 코드는 공통 라이브러리를 만들어 제거할 수 있다.

 

우선 리팩토링 전 아래 코드를 잠깐 훑어보자.

public class UserDao {
    public void insert(User user) throws SQLException {
        Connection con = null;
        PreparedStatement pstmt = null;
        try {
            con = ConnectionManager.getConnection();
            String sql = "INSERT INTO USERS VALUES (?, ?, ?, ?)";
            pstmt = con.prepareStatement(sql);
            pstmt.setString(1, user.getUserId());
            pstmt.setString(2, user.getPassword());
            pstmt.setString(3, user.getName());
            pstmt.setString(4, user.getEmail());

            pstmt.executeUpdate();
        } finally {
            if (pstmt != null) {
                pstmt.close();
            }

            if (con != null) {
                con.close();
            }
        }
    }
    
    public void update(User user) throws SQLException {
        Connection con = null;
        PreparedStatement pstmt = null;
        try {
            con = ConnectionManager.getConnection();
            String sql = "UPDATE USERS SET name=?, email=? where userId=? and password=? ";
            pstmt = con.prepareStatement(sql);
            pstmt.setString(1, user.getName());
            pstmt.setString(2, user.getEmail());
            pstmt.setString(3, user.getUserId());
            pstmt.setString(4, user.getPassword());

            pstmt.executeUpdate();
        } finally {
            if (pstmt != null) {
                pstmt.close();
            }

            if (con != null) {
                con.close();
            }
        }
    }
}

 

우선 이와 같은 중복 코드를 리팩토링하려면 변화가 발생하는 부분( 개발자가 구현할 수 밖에 없는 부분)과 변화가 없는 부분( 공통 라이브러리로 분리할 부분)을 분리해야 한다.

작업 공통 라이브러리 개발자가 구현할 부분
Connection 관리 O X
Statement 관리 O X
ResultSet 관리 O X
SQL X O
Row 데이터 추출 X O
Parameter 선언 X O
Parameter Setting O X
트랜잭션 관리 O X

 

위와 같이 정리를 하면 개발자가 구현해야 할 부분은 SQL 쿼리, (select 쿼리일 경우)조회한 데이터를 추출, 쿼리에 전달한 인자만 구현하면 된다. 

나머지 모든 작업은 공통 라이브러리로 위임할 수 있다.


 

JdbcTemplate를 추상 클래스로 만들자

public abstract class JdbcTemplate {
    public void update(String query) throws Exception {
        Connection con = null;
        PreparedStatement pstmt = null;
        try {
            con = ConnectionManager.getConnection();
            String sql = query;
    		pstmt = con.prepareStatement(sql);
    		pstmt = setValues(pstmt);
    		pstmt.executeUpdate();
        } finally {
            if (pstmt != null) {
                pstmt.close();
            }
            if (con != null) {
                con.close();
            }
        }
    }
    abstract PreparedStatement setValues(PreparedStatement pstmt) throws Exception;
}

 

 

 

위와 같이 변화가 없는 부분을 추상 클래스로 리팩토링했다.

setValues 메서드는 추상 메서드이다. 이를 사용하는 Dao클래스에서 구현해서 사용한다면 JdbcTemplate 클래스와 Dao 클래스와의 의존관계는 자연스럽게 끊어진다.

중요한 점은, 추상 메서드 구현은 Dao 클래스의 메서드에서 익명 클래스로 구현한다는  것이다.

또한, SQL 쿼리와 같이 변경되는 부분을 추상 메서드가 아닌 메서드의 인자로 전달한다면 JdbcTemplate 클래스를 통합할 수 있다.

 

Dao 클래스의 메서드

public void insert(User user) throws Exception {
    JdbcTemplate JdbcTemplate = new JdbcTemplate() {
        @Override
        PreparedStatement setValues(PreparedStatement pstmt) throws Exception{
            pstmt.setString(1, user.getUserId());
            pstmt.setString(2, user.getPassword());
            pstmt.setString(3, user.getName());
            pstmt.setString(4, user.getEmail());
            return pstmt;
        }
    };
    String sql = "INSERT INTO USERS VALUES (?, ?, ?, ?)";
    JdbcTemplate.update(sql);
};
public void update(User user) throws Exception {
    JdbcTemplate JdbcTemplate = new JdbcTemplate() {
        @Override
        PreparedStatement setValues(PreparedStatement pstmt) throws Exception {
            pstmt.setString(1, user.getName());
            pstmt.setString(2, user.getEmail());
            pstmt.setString(3, user.getUserId());
            pstmt.setString(4, user.getPassword());
            return pstmt;
        }
    };
    String sql = "UPDATE USERS SET name=?, email=? where userId=? and password=? ";
    JdbcTemplate.update(sql);
}

 

JdbcTemplate를 사용하는 Dao 클래스의 메서드에 관련된 코드이다

 

 

댓글