서비스 계층은 가급적 특정 구현 기술에 의존하지 않고, 순수하게 유지하는 것이 좋다.
이렇게 하려면 예외에 대한 의존도 함께 해결해야 한다.
예를 들어 서비스가 처리할 수 없는 SQLException에 대한 의존을 제거하려면 어떻게 해야할까?
→ 서비스가 처리할 수 없으므로 repository가 던지는 SQLException
(체크 예외)를 **런타임 예외
**로 전환해서 서비스 계층에 던지자.
이렇게 하면 서비스 계층이 해당 예외를 무시할 수 있기 때문에 특정 구현 기술에 의존하는 부분을 제거하고 서비스 계층을 순수하게 유지할 수 있다
인터페이스 생성
public interface MemberRepository {
Member save(Member member);
Member findById(String memberId);
void update(String memberId, int money);
void delete(String memberId);
}
커스텀 런타임 예외 생성
public class MyDbException extends RuntimeException{
public MyDbException() {
}
public MyDbException(String message) {
super(message);
}
public MyDbException(String message, Throwable cause) {
super(message, cause);
}
public MyDbException(Throwable cause) {
super(cause);
}
}
MemberRepository
/**
* 예외 누수 문제 해결
* 체크 예외를 런타임 예외로 변경
* MemberRepository 인터페이스 사용
* throws SQLException 제거
*/
@Slf4j
@RequiredArgsConstructor
public class MemberRepositoryV4_1 implements MemberRepository{
private final DataSource dataSource;
@Override
public Member save(Member member) { // throws SQLException 제거
String sql = "insert into member(member_id, money) values(?, ?)";
Connection con = null;
PreparedStatement ps = null;
try {
con = getConnection();
ps = con.prepareStatement(sql);
ps.setString(1, member.getMemberId());
ps.setInt(2, member.getMoney());
int count = ps.executeUpdate();
return member;
} catch (SQLException e) {
throw new MyDbException(e); //*런타임 예외
} finally {
JdbcUtils.closeStatement(ps);
DataSourceUtils.releaseConnection(con, dataSource);
}
}
[..]
}