JDBC를 사용하여 데이터베이스가 변경되어도 JDBC 표준 인터페이스만 의존하면 된다.
JDBC가 제공하는 DriverManager는 라이브러리에 등록된 DB 드라이버들을 관리하고, 커넥션을 획득하는 기능일 제공
public class DBConnectionUtil {
public static Connection getConnection() {
try {
Connection connection = DriverManager.getConnection(URL, USERNAME, PASSWORD);
return connection;
} catch (SQLException e) {
throw new IllegalStateException(e);
}
}
}
public Member save(Member member) throws SQLException {
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 e;
} finally {
close(con,pstmt, null);
}
}
//DBConnectionUtil (DriverManager 사용)
private Connection getConnection() {
return DBConnectionUtil.getConnection();
}
//리소스 종료
private void close(Connection con, Statement stmt, ResultSet rs) {
if (rs != null) {
try {
rs.close();
} catch (SQLException e) {
log.info("error",e);
}
}
if (stmt != null) {
try {
stmt.close();
} catch (SQLException e) {
log.info("error",e);
}
}
if (con != null) {
try {
con.close();
} catch (SQLException e) {
log.info("error",e);
}
}
}
커넥션풀은 얻는 이점이 크기 때문에 항상 기본으로 사용
대표적인 커넥션 풀 오픈소스는
'HikariCP', 'commons-dbcp2', 'tomcat-jdbc pool' 등
스프링부트는 hikariCP를 기본으로 제공한다.
DataSource 인터페이스
커넥션을 획득하는 방법을 추상화 하는 인터페이스
public interface DataSource {
Connection getConnection() throws SQLException;
}
대부분의 커넥션 풀은 DataSource 인터페이스를 구현해두었다.
개발자는 DataSource 인터페이스에만 의존하도록 애플리케이션을 작성하면 된다.
DriverManager는 DataSource 인터페이스를 사용하지 않는다.
스프링은 DriverManagerDataSource라는 클래스를 제공한다.
드라이버매니저
Connection con = DriverManager.getConnection(URL,USERNAME,PASSWORD);
데이터소스드라이버매니저
DriverManagerDataSource dataSource = new DriverManagerDataSource(URL,USERNAME,PASSWORD);
dataSource.getConnection();
데이터소스 커넥션풀(HikariDataSource)
HikariDataSource dataSource = new HikariDataSource();
dataSource.setJdbcUrl(URL);
dataSource.setUsernae(USERNAME);
dataSource.setPassword(PASSWORD);
dataSource.setMaximumPoolSize(10); //커넥션풀 개수
dataSource.setPoolName("MyPool"); //커넥션풀 명
dataSource.getConnection();
DataSource를 만들고 필요한 속성들을 사용해서 한 곳에 있어서 향후 변경에 유연함.
사용시에는 설정을 신경쓰지 않고, DataSource의 getConnection()만 호출하여 사용.
private final DataSource dataSource;
public MemberRepositoryV1(DataSource dataSource) {
this.dataSource = dataSource;
}
public Member save(Member member) throws SQLException {
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 e;
} finally {
close(con,pstmt, null);
}
}
//DataSource 의존관계 주입
private Connection getConnection() throws SQLException {
Connection con = dataSource.getConnection();
return con;
}
private void close(Connection con, Statement stmt, ResultSet rs) {
JdbcUtils.closeResultSet(rs);
JdbcUtils.closeConnection(con);
JdbcUtils.closeStatement(stmt);
}