Updated:

1. 개요

데이터베이스 커넥션을 얻기 위해서는 JDBC DriverManager를 통해 직접 얻어올 수도 있고, 커넥션 풀을 사용할 수도 있다. 커넥션 풀도 HikariCP, DBCP2 등 다양한데, 커넥션을 획득하는 방법을 변경할 경우 코드를 변경해야 한다는 문제점이 있다. 스프링에서는 DataSource라는 인터페이스를 제공하여 코드 변경 없이 커넥션 획득 방법을 변경할 수 있다. 이번에는 스프링에서 제공하는 DataSource에 대해 알아보도록 하자.

2. 개발 환경

  • Java 11

  • Spring Boot 2.7.7

3. DataSource

DataSource는 커넥션을 획득하는 방법을 추상화한 인터페이스이다. 해당 인터페이스를 통해 애플리케이션 로직 변경 없이 커넥션 풀을 변경할 수 있다.

1
2
3
4
public interface DataSource extends CommonDataSource, Wrapper {

  Connection getConnection() throws SQLException;
}

4. DriverManager 적용

4-1. 예제 코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
@Slf4j
class MemberRepositoryV1Test {

    MemberRepositoryV1 repository;

    @BeforeEach
    void beforeEach() {
        // 기본 DriverManager - 항상 새로운 커넥션 획득
        DriverManagerDataSource dataSource = new DriverManagerDataSource(URL, USERNAME, PASSWORD);

        repository = new MemberRepositoryV1(dataSource);
    }

    @Test
    void crud() throws SQLException, InterruptedException {
        // save
        Member member = new Member("memberV100", 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);

        sleep(1000);
    }
}

Line 9 : 기본 DriverManager 적용 (항상 새로운 커넥션 획득)

4-2. 실행 결과

5. HikariDataSource 적용

5-1. 예제 코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
@Slf4j
class MemberRepositoryV1Test {

    MemberRepositoryV1 repository;

    @BeforeEach
    void beforeEach() {
        // 커넥션 풀링
        HikariDataSource dataSource = new HikariDataSource();
        dataSource.setJdbcUrl(URL);
        dataSource.setUsername(USERNAME);
        dataSource.setPassword(PASSWORD);

        repository = new MemberRepositoryV1(dataSource);
    }

    @Test
    void crud() throws SQLException, InterruptedException {
        // save
        Member member = new Member("memberV100", 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);

        sleep(1000);
    }
}

Line 9 : HikariCP 적용

5-2. 실행 결과

Updated:

Leave a comment