ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 스프링 DB - DataSource 적용
    카테고리 없음 2023. 11. 23. 13:38

    DataSource 적용

     

    애플리케이션에 DataSource를 적용해보자

     

    기존 코드를 유지하기 위해 기존 코드를 복사해서 새로 만들자

    MemberRepositoryV0 ➡️ MemberRepositoryV1

    MemberRepositoryV0Test ➡️ MemberRepositoryV1Test

     

    MemberRepositoryV1

    package hello.jdbc.repository;
    
    import hello.jdbc.connection.DBConnectionUtil;
    import hello.jdbc.domain.Member;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.jdbc.support.JdbcUtils;
    
    import javax.sql.DataSource;
    import java.sql.*;
    import java.util.NoSuchElementException;
    
    /**
     * JDBC - DriverManager 사용, JdbcUtil 사용
     *
     */
    @Slf4j
    public class MemberRepositoryV1 {
    
        private final DataSource dataSource;
    
        public MemberRepositoryV1(DataSource dataSource){
            this.dataSource = dataSource;
        }
    
        //save()...
        //findById()...
        //update()...
        //delete()...
     
        }
        private void close(Connection con, Statement stmt, ResultSet rs){
    
            JdbcUtils.closeResultSet(rs);
            JdbcUtils.closeStatement(stmt);
            JdbcUtils.closeConnection(con);
            
        }
    
        private Connection getConnection() throws SQLException {
            Connection con = dataSource.getConnection();
            log.info("get connection = {}, class ={}");
            return con;
        }
    }

     

    • DataSource 의존관계 주입
      • 외부에서 DataSource를 주입받아서 사용한다. 이제 직접만든 DBConnectionUtil을 사용하지 않나도 된다.
      • DataSource는 표준 인터페이스 이기 때문에 DriverManagerDataSource에서 HikarDataSource로 변경되어도 해당 코드를 변경하지 않아도 된다.
    • JdbcUtils 편의 메서드
      • 스프링은 JDBC를 편리하게 다룰 수 있는 JdbcUtil라는 편의 메서드를 제공한다.
      • JdbcUtils을 사용하면 커넥션을 좀 더 편리하게 닫을 수 있다.

     

    @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 {
    
            //save
            Member member = new Member("memberV6", 10000);
            repository.save(member);
    
            //findById
            Member findMember = repository.findById(member.getMemberId());
            log.info("findMember={}", findMember);
            Assertions.assertEquals(findMember,member);
    
            //update: money: 10000 -> 20000
            repository.update(member.getMemberId(),20000);
            Member updateMember = repository.findById(member.getMemberId());
            Assertions.assertEquals(updateMember.getMoney(),20000);
    
            //delete
            repository.delete(member.getMemberId());
            Assertions.assertThrows(NoSuchElementException.class,
                    ()->repository.findById(member.getMemberId()));
    
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    
    }
    • MemberRepository은 DataSource 의존 관계 주입이 필요하다.

     

    DriverManagerDataSource사용

    • DriverManagerDataSource를 사용하면 conn0~5번호를 통해서 항상 새로운 커넥션이 생성되어서 사용하는 것을 확인할 수 있다.

    HikariDataSource 사용

    • 커넥션 풀 사용시 conn0 커넥션이 재사용 된 것을 확인할 수 있다.
    • 테스트는 순서대로 실행됙 때문에 커넥션을 사용하고 다시 돌려주는 것을 반복한다. 따라서 conn0만 사용된다.
    • 웹 어플리케이션에 동시에 여러 요청이 들어오면 여러 쓰레드에서 커넥션 풀의 커넥션을 다양하게 가져가는 상황을 확인할 수 있다.

     

    같은 커넥션이 사용될 수 있는 원리

     

    커넥션 풀에서 커넥션을 사용하고 해당 커넥션을 close하게 되면, 커넥션 연결이 끊어 지는 것이 아니라 커넥션 풀로 해당 커넥션을 반환한게 된다.

     

    그래서 save(),findById(),update(),delete()등의 DB와 상호작용이 있는 메서드를 실행 할때 마다 con0이라는 같은 커넥션을 사용하게 되는 것이다.

     

    DI

    DriverManagerDataSource → HikarDataSource로 변경해도 MemberRepository의 코드는 전혀 변경하지 않아도된다. MemberRepositoryV1는 DataSource인터페이스에만 의존하기 때문이다. 이것이 DataSource를 사용하는 장점이다.

    (DI + OCP)

     

    HikariProxyConnection

     

    HikariDataSource에서 커넥션풀을 조회후 return 할때 HikariProxyConnection이라는 객체를 생성을 하고 거기에 실제 커넥션을 매핑한 후 커넥션 풀로 반환하게 된다. 커넥션 풀이 반환 될때 마다 HikariProxyConnection이 새로 생성 되기때문에 HikariProxyConnection의 객체 인스턴스 참조값은 계속 다르다.

     

     

    [출저 - 스프링 DB 1편 - 데이터 접긎 핵심 원리, 김영한]

    https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-db-1

     

    스프링 DB 1편 - 데이터 접근 핵심 원리 - 인프런 | 강의

    백엔드 개발에 필요한 DB 데이터 접근 기술을 기초부터 이해하고, 완성할 수 있습니다. 스프링 DB 접근 기술의 원리와 구조를 이해하고, 더 깊이있는 백엔드 개발자로 성장할 수 있습니다., 백엔

    www.inflearn.com

     

    댓글

Designed by Tistory.