JDBC 등장 이유
애플리케이션 서버에서 데이터베이스를 사용하기 위해서 아래 과정을 진행합니다.
- 커넥션 연결: 주로 TCP/IP를 사용해서 커넥션 연결합니다.
- SQL 전달 : 애플리케이션 서버는 DB가 이해할 수 있는 SQL을 연결된 커넥션을 통해서 DB에 전달합니다.
- 결과 응답: DB는 전달된 SQL을 수행하고 그 결과를 응답합니다. 애플리케이션 서버는 응답 결과를 활용합니다.
여러 데이터베이스는 커넥션을 연결하는 방법과 SQL을 전달하는 방법, 그리고 결과를 응답하는 방법이 모두 다릅니다.
이에 따라 다음과 같은 문제점이 발생합니다.
- 데이터베이스를 다른 종류의 데이터베이스로 변경하면 애플리케이션 서버에 개발된 데이터베이스 사용 코드도 함께 변경해야 합니다.
- 개발자가 각각의 데이터베이스마다 커넥션 연결, SQL 전달, 그리고 그 결과를 응답받는 방법을 새로 학습해야 합니다.
이를 해결하기 위해 JDBC가 등장하였습니다.
JDBC 드라이버
JDBC는 자바 표준으로, 자바에서 데이터베이스에 접속할 수 있도록 하는 자바 API입니다.
대표적으로 다음 3가지 기능을 인터페이스로 정의해서 제공합니다.
Connection : 연결 담당
Statement : SQL을 담은 내용
ResultSet : SQL 요청에 대한 응답
각각의 DB 벤더에서 자신들의 DB에 맞도록 해당 인터페이스들을 구현하여 라이브러리로 제공하는데, 이것을 JDBC 드라이버라고 합니다.
JDBC 의 한계
JDBC는 결국 모든 데이터베이스들에 대하여 표준화된 기능만을 제공하기 때문에 데이터베이스마다 SQL이나 데이터타입 등의 일부 사용법은 서로 다릅니다.
ANSI SQL 표준이 있다곤 하여도 이는 일반적인 부분에 대해서만 공통화하였기 때문에 한계가 있으며, 따라서 DB를 변경하면 SQL은 해당 DB에 맞게 변경해야 합니다.
(JPA를 사용하면 이러한 부분도 대부분 해결 가능합니다.)
최신 데이터 접근 기술
JDBC는 오래된 기술이며, 최근에는 JDBC를 직접 사용하기 보다는 JDBC를 편리하게 사용하는 다양한 기술이 존재합니다.
대표적으로는 SQL Mapper와 ORM 기술로 나눌 수 있습니다.
SQL Mapper
JDBC를 편리하게 사용하도록 도와주는 기능이며, SQL의 응답 결과를 객체로 편리하게 변환해줍니다.
그러나 개발자가 직접 SQL을 작성해야 한다는 단점이 있습니다.
대표적으로는 스프링의 JdbcTemplate와 MyBatis가 있습니다.
ORM
ORM은 객체를 관계형 데이터베이스 테이블과 매핑해주는 기술입니다.
이 기술 덕분에 개발자는 반복적인 SQL을 직접 작성하지 않고, ORM 기술이 개발자 대신에 SQL을 동적으로 만들어 실행해줍니다.
추가로 각각의 데이터베이스마다 다른 SQL을 사용하는 문제도 해결해줍니다.
대표적으로는 JPA가 있으며, JPA의 구현체로는 하이버네이트와 이클립스링크등이 있습니다.
기본 데이터 생성
create table member(
member_id varchar(10),
money integer not null default 0,
primary key (member_id)
);
insert into member(member_id, money) values ('hi1', 10000);
insert into member(member_id, money) values ('hi2', 20000);
데이터베이스 연결
public abstract class ConnectionConst {
public static final String URL = "jdbc:h2:tcp://localhost/~/test";
public static final String USERNAME = "sa";
public static final String PASSWORD = "";
}
import lombok.extern.slf4j.Slf4j;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import static com.example.demo.connection.ConnectionConst.*;
@Slf4j
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);
}
}
}
import lombok.extern.slf4j.Slf4j;
import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.Test;
import java.sql.Connection;
@Slf4j
class DBConnectionUtilTest {
@Test
void test() {
Connection connection = DBConnectionUtil.getConnection();
Assertions.assertThat(connection).isNotNull();
}
}
이를 실행하면 h2 DB 드라이버가 제공하는 h2 전용 커넥션인 org.h2.jdbc.JdbcConnection을 반환합니다.
이때 어떻게 아무 정보 없이 h2 커넥션을 얻어오는지에 대해 살펴보겠습니다.
이는 JDBC에서 제공하는 DriverManager에서 얻어지는데, DriverManager는 라이브러리에 등록된 드라이버들을 관리하고, 커넥션을 획득하는 기능을 제공합니다.
- 커넥션이 필요하면 DriverManager.getConnection()을 호출합니다.
- DriverManager는 라이브러리에 등록된 드라이버 목록을 자동으로 인식합니다. 이 드라이버들에게 순서대로 다음 정보를 넘겨서 커넥션을 획득할 수 있는지 확인합니다.
import com.example.demo.connection.DBConnectionUtil;
import com.example.demo.domain.Member;
import lombok.extern.slf4j.Slf4j;
import java.sql.*;
@Slf4j
public class MemberRepositoryV0 {
public Member save(Member member) throws SQLException {
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.memberId());
pstmt.setInt(2, member.money());
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(); // Exception
} catch (SQLException e) {
log.info("error", e);
}
}
if (stmt != null) {
try {
stmt.close(); // Exception
} catch (SQLException e) {
log.info("error", e);
}
}
if (con != null) {
try {
con.close();
} catch (SQLException e) {
log.info("error", e);
}
}
}
private static Connection getConnection() {
return DBConnectionUtil.getConnection();
}
}
'모각코 > 2022 동계 모각코 : 미남과 야수' 카테고리의 다른 글
[모각코] 2022 동계 모각코 3회차 결과 (0) | 2023.01.12 |
---|---|
[모각코] 2022 동계 모각코 3회차 목표 (0) | 2023.01.12 |
[모각코] 2022 동계 모각코 2회차 결과 (0) | 2023.01.05 |
[모각코] 2022 동계 모각코 2회차 목표 (0) | 2023.01.05 |
[모각코] 2022 동계 모각코 1회차 목표 (0) | 2022.12.29 |