스프링은 기본 커넥션 풀로 HikariCP를 사용한다.
다른 커넥션 풀과 마찬가지로 HikariCP 또한 DataSource 인터페이스를 구현한 구현체인 HikariDataSource를 제공한다.
@Test
void dataSourceConnectionPool() throws SQLException, InterruptedException {
//커넥션 풀링
HikariDataSource dataSource = new HikariDataSource();
dataSource.setJdbcUrl(URL);
dataSource.setPassword(PASSWORD);
dataSource.setUsername(USERNAME);
dataSource.setMaximumPoolSize(10);
dataSource.setPoolName("MyPool");
useDataSource(dataSource);
Thread.sleep(1000);
}
private void useDataSource(DataSource dataSource) throws SQLException{
Connection con1 = dataSource.getConnection();
Connection con2 = dataSource.getConnection();
log.info("connection1={} class={}", con1, con1.getClass());
log.info("connection2={} class={}", con2, con2.getClass());
}
애플리케이션이 시작할 때 히카리CP는 별도의 쓰레드로 커넥션을 얻어온다. 상대적으로 많은 시간이 걸리기 떄문에 앱 실행시간에 영향을 미치지 않게 하기 위함이다.
그렇기에 Thread.sleep(1000);
를 넣어 로그가 다 찍히도록 했다.
14:11:01.706 [MyPool connection adder] DEBUG com.zaxxer.hikari.pool.HikariPool - MyPool - Added connection conn2: url=jdbc:h2:tcp://localhost/~/test user=SA
14:11:01.709 [MyPool connection adder] DEBUG com.zaxxer.hikari.pool.HikariPool - MyPool - Added connection conn3: url=jdbc:h2:tcp://localhost/~/test user=SA
14:11:01.712 [MyPool connection adder] DEBUG com.zaxxer.hikari.pool.HikariPool - MyPool - Added connection conn4: url=jdbc:h2:tcp://localhost/~/test user=SA
14:11:01.721 [MyPool connection adder] DEBUG com.zaxxer.hikari.pool.HikariPool - MyPool - Added connection conn5: url=jdbc:h2:tcp://localhost/~/test user=SA
14:11:01.726 [MyPool connection adder] DEBUG com.zaxxer.hikari.pool.HikariPool - MyPool - Added connection conn6: url=jdbc:h2:tcp://localhost/~/test user=SA
14:11:01.732 [MyPool connection adder] DEBUG com.zaxxer.hikari.pool.HikariPool - MyPool - Added connection conn7: url=jdbc:h2:tcp://localhost/~/test user=SA
14:11:01.737 [MyPool connection adder] DEBUG com.zaxxer.hikari.pool.HikariPool - MyPool - Added connection conn8: url=jdbc:h2:tcp://localhost/~/test user=SA
14:11:01.740 [MyPool connection adder] DEBUG com.zaxxer.hikari.pool.HikariPool - MyPool - Added connection conn9: url=jdbc:h2:tcp://localhost/~/test user=SA
14:11:01.740 [MyPool connection adder] DEBUG com.zaxxer.hikari.pool.HikariPool - MyPool - After adding stats (total=10, active=2, idle=8, waiting=0)
만약 커넥션 풀에 남은 커넥션이 없다면?
다른 커넥션이 반환될 때까지 기다린다. 이 때 일정시간이 지나면 에러를 발생시킨다.
HikariDataSource dataSource = new HikariDataSource();
dataSource.setJdbcUrl(URL);
dataSource.setUsername(USERNAME);
dataSource.setPassword(PASSWORD);
기존에 상용했던 DriverManagerDataSource도 DataSource 인터페이스의 구현체이기 때문에 HikariDataSource
로 갈아끼기만 하면 사용이 가능하다.
-> DI 관점에선 DataSource라는 인터페이스에 의존하기 때문에 코드를 변경하지 않고 간단히 구현체를 갈아끼울 수 있다.
14:31:54.278 [main] INFO hello.jdbc.repository.MemberRepositoryV1 - get connection = HikariProxyConnection@1893960929 wrapping conn0: url=jdbc:h2:tcp://localhost/~/test user=SA, class=class com.zaxxer.hikari.pool.HikariProxyConnection
14:31:54.295 [main] INFO hello.jdbc.repository.MemberRepositoryV1 - get connection = HikariProxyConnection@1564698139 wrapping conn0: url=jdbc:h2:tcp://localhost/~/test user=SA, class=class com.zaxxer.hikari.pool.HikariProxyConnection
14:31:54.341 [main] INFO hello.jdbc.repository.MemberRepositoryV1 - get connection = HikariProxyConnection@1126185196 wrapping conn0: url=jdbc:h2:tcp://localhost/~/test user=SA, class=class com.zaxxer.hikari.pool.HikariProxyConnection
14:31:54.341 [main] INFO hello.jdbc.repository.MemberRepositoryV1 - get connection = HikariProxyConnection@2108297149 wrapping conn0: url=jdbc:h2:tcp://localhost/~/test user=SA, class=class com.zaxxer.hikari.pool.HikariProxyConnection
14:31:54.345 [main] INFO hello.jdbc.repository.MemberRepositoryV1 - get connection = HikariProxyConnection@1530295320 wrapping conn0: url=jdbc:h2:tcp://localhost/~/test user=SA, class=class com.zaxxer.hikari.pool.HikariProxyConnection
위의 코드는 히카리풀을 사용해 CRUD 작업을 수행한 후 출력된 로그다. 모든 로그에 conn0 로그만 찍히는 것은 커넥션 풀에서 커넥션을 하나 꺼내 사용하고 그 후에 다시 반납했기 때문이다.
같은 커넥션을 사용했지만 커넥션풀에서 커넥션을 꺼낼 때 커넥션을 감싸기 위한HikariProxyConnection
객체를 새로 생성하기 때문에 새로운 인스턴스가 출력되는 것이다.