Spring DB : JdbcTemplate을 이용한 반복 문제 해결
- Spring/Spring DB
- 2022. 5. 19.
반응형
이 글은 인프런 김영한님의 강의를 복습하며 작성한 글입니다.
JDBC 기술은 반복을 부른다.
앞서 여러 추상화 과정들을 통해 코드를 개선해나가는 작업을 해왔다. 그렇지만 아직까지 개선의 여지가 있는 부분이 남아있다. 아래 코드를 한번 살펴보자.
@Override
public Member findById(String memberId){
String sql = "select * from member where member_id = ?";
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
Connection conn = getConnection();
pstmt = conn.prepareStatement(sql);
pstmt.setString(1, memberId);
rs = pstmt.executeQuery();
log.info("Connection = {}, class = {}", conn,conn.getClass());
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) {
log.error("error", e);
throw exTranslator.translate("find", sql, e);
}finally {
JdbcUtils.closeResultSet(rs);
JdbcUtils.closeStatement(pstmt);
}
}
위 코드에서 살펴보면, 계속 반복되는 부분이 어떤 것인지 대충 감을 잡을 수 있다.
- 커넥션 조회, 커넥션 동기화
- PreparedStatement 생성 및 파라미터 바인딩
- 쿼리 실행
- ResultSet 바인딩
- 예외 발생 시, 스플이 예외 변환기 실행
- 리소스 종료
위에서 발생하는 반복들은 대부분 JDBC 기술을 사용하기 때문에 발생하는 것이다. 이런 반복적인 부분들을 해결할 수 있다면, 코드가 아주 아름답게 리팩토링 될 것이다. 그렇다면 어떤 방식으로 접근할 수 있을까?
먼저 위 구문들은 실제 비즈니스 로직 사이에 적용되어있다. 따라서 이런 것들은 따로 메서드로 빼서 처리를 할 수 없다. 이런 경우에는 템플릿 콜백 패턴을 이용해서 처리할 수 있다. 다행히 이런 문제를 해결하기 위한 템플릿 콜백 패턴이 구현되어있다. 바로 JdbcTemplate이다. 위에서 발생한 문제들은 JdbcTemplate을 이용하면 깔끔하게 처리할 수 있다.
JdbcTemplate을 이용한 코드 리팩토링
Jdbc이를 이용하면 다음과 같이 불필요한 코드의 반복을 제거해준다.
@Slf4j
public class MemberRepositoryV5 implements MemberRepository{
private final JdbcTemplate jdbcTemplate;
public MemberRepositoryV5(DataSource dataSource) {
this.jdbcTemplate = new JdbcTemplate(dataSource);
}
@Override
public Member save(Member member) {
String sql = "insert into member(member_id, money) values(?,?)";
jdbcTemplate.update(sql,member.getMemberId(), member.getMoney());
return member;
}
@Override
public Member findById(String memberId){
String sql = "select * from member where member_id = ?";
return jdbcTemplate.queryForObject(sql, memberRowMapper(), memberId);
}
@Override
public void update(String memberId, int money){
String sql = "update member set money = ? where member_id = ?";
jdbcTemplate.update(sql, memberId, money);
}
@Override
public void delete(String memberId){
String sql = "delete from member where member_id=?";
jdbcTemplate.update(sql, memberId);
}
private RowMapper<Member> memberRowMapper() {
return (rs, rowNum) -> {
Member member = new Member();
member.setMemberId(rs.getString("member_id"));
member.setMoney(rs.getInt("money"));
return member;
};
}
}
정리
- JdbcTemplate은 트랜잭션을 위한 커넥션 동기화 / 예외 발생 시 스프링 예외 변환기도 자동으로 실행해준다.
- 서비스 계층의 순수성
- 트랜잭션 추상화 + 트랜잭션 AOP 덕분에 서비스 계층의 순수성을 최대한 유지하면서 서비스 계층에서 트랜잭션을 사용할 수 있다.
- 스프링에 제공하는 예외 추상화 + 예외 변환기 덕분에, DB 접근 기술이 변경되어도 서비스 계층의 순수성을 유지하면서 예외도 사용할 수 있다.
- 서비스 계층이 리포지토리 인터페이스에 의존한 덕분에 향후 리포지토리가 다른 구현 기술로 변경되어도 서비스 계층을 순수하게 유지할 수 있다.
- 리포지토리에서 JDBC를 사용하는 반복 코드가 JdbcTemplate에 의해 제거되었다.
'Spring > Spring DB' 카테고리의 다른 글
Spring DB : DB 테스트 (0) | 2022.07.04 |
---|---|
Spring DB : JdbcTemplate (0) | 2022.06.11 |
Spring DB : Spring의 예외 추상화 이해 (0) | 2022.05.19 |
Spring DB : 데이터 접근 예외 직접 만들기 (0) | 2022.04.29 |
Spring DB : 스프링과 문제 해결, 예외 처리 / 반복 (0) | 2022.04.28 |