이번에는 애플리케이션에 DataSource 를 적용해봅시다.
참고로 기존 코드를 유지하기 위해 기존 코드를 복사해서 새로 만들겠습니다.
/**
* JDBC - DataSource 사용, JDBCUtils 사용
*/
@Slf4j
public class MemberRepositoryV1 {
//...1
private final DataSource dataSource;
public MemberRepositoryV1(DataSource dataSource) {
this.dataSource = dataSource;
}
//save()...
//findById()...
//update()....
//delete()....
//...2
private void close(Connection con, Statement stmt, ResultSet rs) {
JdbcUtils.closeResultSet(rs);
JdbcUtils.closeStatement(stmt);
JdbcUtils.closeConnection(con);
}
//...1
private Connection getConnection() throws SQLException {
Connection con = dataSource.getConnection();
log.info("get connection={}, class={}", con, con.getClass());
return con;
}
}
외부에서 DataSource 를 주입 받아서 사용합니다.
이제 MemberRepositoryV0과 다르게 커넥션을 획득하기 위해 추출한 getConnection()에서 직접 만든 DBConnectionUtil 을 사용하지 않아도 됩니다.
DataSource 는 표준 인터페이스 이기 때문에 DriverManagerDataSource 에서 HikariDataSource 로 변경되어도 해당 코드를 변경하지 않아도 됩니다.
스프링은 JDBC를 편리하게 다룰 수 있는 JdbcUtils 라는 편의 메서드를 제공합니다.
JdbcUtils 을 사용하면 커넥션을 좀 더 편리하게 닫을 수 있습니다.
아래의 메서드들은 기존에 작성했던 코드보다 훨씬 안전하게 잘 짜놨습니다.
@Slf4j
class MemberRepositoryV1Test {
MemberRepositoryV1 repository;
@BeforeEach
void beforeEach() throws Exception {
//기본 DriverManager - 항상 새로운 커넥션 획득
DriverManagerDataSource dataSource = new DriverManagerDataSource(URL, USERNAME, PASSWORD);
repository = new MemberRepositoryV1(dataSource);
}
@Test
void crud() throws SQLException {
//save
Member member = new Member("memberV0", 10000);
repository.save(member);
//findById
Member findMember = repository.findById(member.getMemberId());
log.info("findMember={}", findMember);
assertThat(findMember).isEqualTo(member);
//update: money: 10000 -> 20000
repository.update(member.getMemberId(), 20000);
Member updatedMember = repository.findById(member.getMemberId());
assertThat(updatedMember.getMoney()).isEqualTo(20000);
//delete
repository.delete(member.getMemberId());
assertThatThrownBy(() -> repository.findById(member.getMemberId()))
.isInstanceOf(NoSuchElementException.class);
}
}
MemberRepositoryV1 은 DataSource 의존관계 주입이 필요합니다.
기본 DriverManager을 사용해서 항상 새로운 커넥션 획득하도록 설정했습니다.