JDBC

바그다드·2023년 3월 25일
0
post-thumbnail

JDBC(Java Database Connectivity)

자바에서 데이터베이스에 접속할 수 있도록 하는 자바 API

  • CRUD기능 제공

1. JDBC 초기

db와 연동이 필요할 때마다 커넥션을 새로 생성

  • DriverManager를 이용해 커넥션 직접 생성
public abstract class ConnectionConst { // db연결 정보
    public static final String URL = "jdbc:h2:tcp://localhost/~/test";
    public static final String USERNAME = "sa";
    public static final String PASSWORD = "";
}
public class DBConnectionUtil{
	 // 커넥션 생성
    public static Connection getConnection(){
        try {
            Connection connection = DriverManager.getConnection(URL, USERNAME, PASSWORD);
            log.info("get connection={}, class={}", connection, connection.getClass());
            return connection;
        } catch (SQLException e) {
            throw new IllegalStateException(e);
        }
    }
}
public Member save(Member member) throws SQLException {
		// db연동
        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.execute();
            return member;
        } catch (SQLException e) {
            log.error("db error", e);
            throw e;
        }finally {
            close(con, pstmt, null);

        }
    }
  • 반복되는 코드가 많음

  • 그때 그때 커넥션을 생성하기 때문에 속도가 느림

  • 커넥션

  • 다만 아래와 같이 비즈니스 로직은 순수한 자바 코드로 이루어져 있음

	public void accountTrancefer(String fromId, String toId, int money) throws SQLException {
        Member fromMember = memberRepository.findById(fromId);
        Member toMember = memberRepository.findById(toId);

        memberRepository.update(fromId, fromMember.getMoney() - money);
        validation(toMember);
        memberRepository.update(toId, toMember.getMoney() + money);
    }
    private void validation(Member toMember) {
        if (toMember.getMemberId().equals("ex")) {
            throw new IllegalStateException("이체중 예외 발생");
        }
    }

1.5 DataSource

  • 커넥션을 획득하는 방법을 추상화하는 인터페이스
  • 기존에 drivermanager를 통해 커넥션을 새로 생성하던 방식에서 커넥션 풀을 이용하는 방식으로 변경이 생기면 어플리케이션 로직을 수정해야 함(ocp위반)
  • 인터페이스 핵심은 커넥션 조회 하나이다.
    - SRP(단일 책임 원칙)

DriverManagerDataSource 적용

@Slf4j
public class ConnectionTest {
  @Test
  void driverManager() throws SQLException {
    Connection con1 = DriverManager.getConnection(URL, USERNAME, PASSWORD);
    Connection con2 = DriverManager.getConnection(URL, USERNAME, PASSWORD);
    log.info("connection={}, class={}", con1, con1.getClass());
    log.info("connection={}, class={}", con2, con2.getClass());
  }
  
  @Test
  void dataSourceDriverManager() throws SQLException {
    //DriverManagerDataSource - 항상 새로운 커넥션 획득
    DriverManagerDataSource dataSource = new DriverManagerDataSource(URL,
    USERNAME, PASSWORD);
    useDataSource(dataSource);
  }
  
  private void useDataSource(DataSource dataSource) throws SQLException {
    Connection con1 = dataSource.getConnection();
    Connection con2 = dataSource.getConnection();
    log.info("connection={}, class={}", con1, con1.getClass());
    log.info("connection={}, class={}", con2, con2.getClass());
  }
}
  • DataSource를 이용해 커넥션을 획득
  • 이를 통해 DataSource를 만드는 설정,
  • 호출(getConnection())해서 사용하는 사용 부분으로 나뉨

2. 커넥션 풀 도입

커넥션을 미리 만들어놓고 필요할 때마다 꺼내 사용

 	private final DataSource dataSource;

    public MemberRepositoryV1(DataSource dataSource) {
        this.dataSource = dataSource;
    }
    
    private Connection getConnection() throws SQLException {
        Connection con = dataSource.getConnection();
        log.info("get connection={}, class={}", con, con.getClass());

        return con;
    }
@BeforeEach
void beforeEach() throws Exception {
    //기본 DriverManager - 항상 새로운 커넥션 획득
    //DriverManagerDataSource dataSource =
    // new DriverManagerDataSource(URL, USERNAME, PASSWORD);
    
    //커넥션 풀링: HikariProxyConnection -> JdbcConnection
    HikariDataSource dataSource = new HikariDataSource();
    dataSource.setJdbcUrl(URL);
    dataSource.setUsername(USERNAME);
    dataSource.setPassword(PASSWORD);
	repository = new MemberRepositoryV1(dataSource);
}

  • 커넥션 풀을 사용하게 되면 커넥션을 빌려와 사용하고 다시 반납하는 식으로 이뤄지기 때문에 같은 커넥션(위 사진에서는 conn0)이 계속 사용되는 것을 알 수 있음
  • DataSource를 이용하였기 때문에 기존 DriverManagerDataSource에서 HikariDataSource로 바뀌었는데도 MemberRepositoryV1은 수정하지 않아도 됨
profile
꾸준히 하자!

0개의 댓글