티스토리 뷰
JDBC 사용 이유
관계형 데이터 베이스에는 상당히 많은 종류가 존재
문제점
- 데이터 베이스를 다른 종류의 데이터 베이스로 변경하면 애플리케이션 서버에 개발된 데이터 베이스 사용 코드도 함께 변경
- 개발자가 각각의 데이터 베이스마다 커넥션 연결 SQL 전달 결과 응답 받는게 다 다름
❗ 해결을 위해 JDBC 표준 인터페이스의 등장
✅ JDBC 표준 인터페이스
- 자바에서 데이터베이스에 접속할 수 있도록 하는 자바 API
- 데이터 베이스에서 자료를 쿼리하거나 업데이트하는 방법을 제공
- 크게 3가지 기능을 제공
- 연결
- SQL을 담은 내용
- SQL 요청 응답
🤔 jdbc 에서 connection 얻기
- JDBC가 제공하는 DriverManager.getConnection() 의 사용
- DataSource 상속 받은 DriverManagerDataSource 사용하기 (spring이 제공)DataSource.getConnection() 사용
- ✅ 1 에서 2번이 되면서 매번 url, username, password 를 입력했으나 (1번) 한번만 입력하기만 되게 바뀜
- 커넥션 풀 사용
결국 커넥션 풀로 사용할 때도 DataSource.getConnection() 을 사용한다.
🖍 DriverManger.getConnection()
jdbc 는 인터페이스로서 각 구현체들은 관계형 DB 마다 따로 구현이 되어있다. (라이브러리에 저장)
- DriverManager 는 라이브러리에 등록된 드라이버 목록을 자동으로 인식한다.
- 드라이버들에게 순서대로 URL, user, password 정보를 넘겨 커넥션을 획득할 수 있는지 확인한다.
- url 의 prefix를 기준으로 확인한다.
public class DBConnectionUtil {
public static Connection getConnection() {
try {
// TCP/IP 를 사용해 매번 새로운 커넥션 획득하기
// DataSource 구현체가 아니기 때문에 Connection 을 얻기 위해 매번 정보를 넘겨야한다.
Connection connection = DriverManager.getConnection(URL, USERNAME, PASSWORD);
log.info("get connection={}, class={}", connection, connection.getClass());
return connection;
} catch (SQLException e) {
throw new IllegalStateException(e);
}
}
}
지금까지의 흐름 요약
- jdbc에서 데이터베이스를 사용하기 위해서 커넥션을 위한 URL, USER, PASSWORD
- 커넥션을 얻기위해 DriverManager.getConnection 사용 (매번 설정 정보 넘겨야 함)
커넥션을 얻을때 현재 라이브러리 정보 + URL을 통해 구현체 주입 - 얻은 커넥션으로 비지니스 로직 수행
- 결국 jdbc 의 등장 첫번째 이유는 다양한 db의 커넥션 지원이다. (인터페이스를 통해)
비지니스 로직 구현
회원 등록하기
🖥 회원 등록 Jdbc 이용
@Slf4j
public class MemberRepositoryV0 {
public Member save(Member member) throws SQLException {
// insert sql 준비
String sql = "insert into member(member_id, money) values(?, ?)";
Connection con = null;
// 데이터 베이스에 전달할 SQL과 파라미터로 전달할 데이터 준비
PreparedStatement pstmt = null;
try {
con = getConnection();
pstmt = con.prepareStatement(sql);
// 파라미터 할당
pstmt.setString(1, member.getMemberId());
pstmt.setInt(2, member.getMoney());
// 커넥션을 통해 SQL 전달
pstmt.executeUpdate();
return member;
} catch (SQLException e) {
log.error("db error", e);
throw e;
} finally {
//커넥션 닫기
close(con, pstmt, null);
}
}
// 리소스 정리하기
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);
}
} }
private Connection getConnection() {
return DBConnectionUtil.getConnection();
}
}
Jdbc 의 조회
🖥 Jdbc 에서의 조회 쿼리
public Member findById(String memberId) throws SQLException {
String sql = "select * from member where member_id = ?";
Connection con = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
con = getConnection();
pstmt = con.prepareStatement(sql);
pstmt.setString(1, memberId);
// iterator 형식으로 결과 값을 받아온다.
rs = pstmt.executeQuery();
if (rs.next()) {
Member member = new Member();
member.setMemberId(rs.getString("member_id"));
member.setMoney(rs.getInt("money"));
return member;
} else {
throw new NoSuchElementException("member not found memberId=" + memberId); }
} catch (SQLException e) {
log.error("db error", e);
throw e;
} finally {
close(con, pstmt, rs);
}
}
'Spring > JPA' 카테고리의 다른 글
트랜잭션 이해하기 (1) | 2022.08.23 |
---|---|
커넥션 풀 (0) | 2022.08.23 |
JPA - 값 타입 (0) | 2022.08.23 |
프록시와 연관관계 관리 (0) | 2022.08.23 |
고급 매핑 (0) | 2022.08.23 |
댓글
11-08 12:46
- Total
- Today
- Yesterday
링크