스프링/5. 스프링 DB-1

41. 예외 추상화 적용.

sdafdq 2023. 10. 6. 12:28

간단하다. 

@Slf4j
public class MemberRepositoryV4_2 implements MemberRepository{
    private final DataSource dataSource;
    private final SQLExceptionTranslator exTranslator;

    public MemberRepositoryV4_2(DataSource dataSource) {
        this.dataSource = dataSource;
        this.exTranslator = new SQLErrorCodeSQLExceptionTranslator(dataSource);
    }

    @Override
    public Member save(Member member){
        String sql = "insert into member(member_id, money) values(?,?)";

        Connection con = null;
        PreparedStatement pstmt = null;

        try {
            con = getConnection();
            pstmt = con.prepareStatement(sql);
            pstmt.setString(1, member.getMemberId());
            pstmt.setInt(2, member.getMoney());
            pstmt.executeUpdate();
            return member;
        }catch (SQLException e){
            throw exTranslator.translate("save", sql, e);
        }finally {
            close(con,pstmt, null);
        }
    }

    @Override
    public Member findById(String memberId){
        String sql = "select * from member where member_id = ?";
        Connection con = null;
        PreparedStatement pstmt = null;
        ResultSet rs = null;

        try {
            con = getConnection();
            pstmt = con.prepareStatement(sql);
            pstmt.setString(1, memberId);

            rs = pstmt.executeQuery();
            if(rs.next()){
                Member member =new Member();
                member.setMemberId(rs.getString("member_id"));
                member.setMoney(rs.getInt("money"));
                return member;
            }else{
                throw new NoSuchElementException("member not found memberId = " + memberId);
            }
        } catch (SQLException e){
            throw exTranslator.translate("findById", sql, e);
        }finally {
            close(con, pstmt, rs);
        }
    }


    private void close(Connection con, Statement stmt, ResultSet rs){
        JdbcUtils.closeResultSet(rs);
        JdbcUtils.closeStatement(stmt);
        DataSourceUtils.releaseConnection(con, dataSource);
    }


    @Override
    public void update(String memberId, int money){
        String sql = "update member set money=? where member_id=?";

        Connection con = null;
        PreparedStatement pstmt = null;

        try{
            con = getConnection();
            pstmt = con.prepareStatement(sql);
            pstmt.setInt(1, money);
            pstmt.setString(2, memberId);
            int result = pstmt.executeUpdate();
            log.info("result = {}",result);
        }catch(SQLException e){
            throw exTranslator.translate("update", sql, e);
        }finally {
            close(con, pstmt,null);
        }
    }

    @Override
    public void delete(String memberId){
        String sql = "delete from member where member_id=?";

        Connection con = null;
        PreparedStatement pstmt = null;
        try{
            con = getConnection();
            pstmt = con.prepareStatement(sql);
            pstmt.setString(1,memberId);
            pstmt.executeUpdate();
        }catch(SQLException e){
            throw exTranslator.translate("delete", sql, e);
        }finally {
            close(con, pstmt, null);
        }
    }

     public Connection getConnection() throws SQLException {
        Connection con = DataSourceUtils.getConnection(dataSource);

        return con;
    }
}

에러 번역기를 생성해주고(생성할 때 dataSource를 넣어준다. 확실히 그 편이 DB의 정체를 알아서 에러코드 아는 데 더 효율적일듯 싶다.) 그 다음 이제 예외를 예외번역기에 (메시지, sql문, 에러객체)를 넣어서 특정 기술에 종속적이지 않은 스프링이 제공해주는 예외를 종류에 맞게 잘 반환해 준다. 이럼 끝이다.

이렇게 하면 이제 어떤 DB던 간에

이게 다는 아니지만, 저런 종류에 맞춰 잘 반환해 줄 것이다.

 

 

이제 이것은 특정한 기술에 종속적인 예외들이 아니라,

서비스에서도 try catch로 예외 발생 시 처리가 가능하거나 혹은 따로 처리하고 싶은 것이 있을 때 처리할 수 있다.

 

이제 이러면 JDBC에서 JPA등 DB기술이나 DB를 바꿔 끼워도 비슷한 에러면 똑같은 예외를 발생시켜 충분히 구분이 가능하다.