일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- 세션타임아웃설정
- 세션만들어보기
- gradle오류
- HTTP상태코드
- no cache
- 인증체크
- hikaricp
- must revalidate
- 300
- supportParameter
- www-Authenticate
- Could not find or load main class worker.org.gradle.process.internal.worker.GradleWorkerMain
- HTTP API
- 조건부요청
- 검증헤더
- http
- 프록시객체
- etag
- Not Modified
- 서블릿http세션
- 쿠키보안문제
- max age
- Expires
- 서블릿필터
- 캐시
- 프록시 캐시 서버
- resolveArgument
- 양쪽 모두 값 설정
- UrlResource
- 쿠키생명주기
- Today
- Total
복습을 위한
DriverManager, Connection, Statement, ResultSet 본문
SQL Mapper인 JdbcTemplate과 MyBatis나 ORM기술인 JPA나 결국 내부에서는JDBC를 사용한다.
JDBC가 어떻게 동작하는지 알아보자.
대표적으로 다음 3가지 기능을 표준 인터페이스로 정의해서 제공한다.
java.sql.Connection - 연결
java.sql.Statement - SQL을 담은 내용 (구현할 땐 상속받은 PreparedStatement 권장(바인딩가능, 기능 더많음, 보안강화)
java.sql.ResultSet - SQL 요청 응답
자바는 이렇게 표준 인터페이스를 정의해두었다. 이제부터 개발자는 이 표준 인터페이스만 사용해서 개발하면 된다. 그런데 인터페이스만 있다고해서 기능이 동작하지는 않는다. 이 JDBC 인터페이스를 각각의 DB 벤더(회사)에서 자신 의 DB에 맞도록 구현해서 라이브러리로 제공하는데, 이것을 JDBC 드라이버라 한다. 예를 들어서 MySQL DB에 접근 할 수 있는 것은 MySQL JDBC 드라이버라 하고, Oracle DB에 접근할 수 있는 것은 Oracle JDBC 드라이버라 한다.
나는 h2데이터베이스를 사용한 간단한 학습을 해보겠다.
h2데이터베이스에 접근하기 위한 정보를 상수로 일단 만들어두었다.
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 = "0000";
}
데이터베이스에 연결하려면 JDBC가 제공하는 DriverManager.getConnection(..) 를 사용하면 된다. 이렇게 하면 라이브러리에 있는 데이터베이스 드라이버를 찾아서 해당 드라이버가 제공하는 커넥션을 반환해준다. 여기서는 H2 데이터베이스 드라이버가 작동해서 실제 데이터베이스와 커넥션을 맺고 그 결과를 반환해준다.(프로젝트를 시작할 때 사용할 데이터베이스 드라이버를 라이브러리에 추가해주자)
@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();
}
}
}
//데이터베이스에 연결하려면 JDBC가 제공하는 DriverManager.getConnection(..) 를 사용하면 된다. 이렇게
//하면 라이브러리에 있는 데이터베이스 드라이버를 찾아서 해당 드라이버가 제공하는 커넥션을 반환해준다. 여기서는
//H2 데이터베이스 드라이버가 작동해서 실제 데이터베이스와 커넥션을 맺고 그 결과를 반환해준다
insert,select,update,delete코드
/*
* JDBC -DriverManger사용 가장 예전 방식
* */
@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.getMemberId());//?,?에 값 바인딩하기
pstmt.setInt(2, member.getMoney());
pstmt.executeUpdate();//실제전달메소드 데이터변경할때 //해당메소드는 쿼리를 실행하고 영향받은 row수를 반환한다.(int반환)
return member;
} catch (SQLException e) {
log.error("db error", e);
throw e;
} finally {
close(con, pstmt, null); //다 끝나면 닫아줘야한다. 닫을 때는 역순
}
}
//주어진 memberId에 해당하는 회원 정보를 데이터베이스에서 조회하고, 그 결과를 Member 객체에 저장하는 메소드
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);
rs = pstmt.executeQuery();//select 쿼리 결과를 담고있는 ResultSet객체반환
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);
}
}
public void update(String memberId, int money) throws SQLException {
String sql ="update member set money=? where member_id=?";
Connection con =null;
PreparedStatement pstmt = null;
try {
con = getConnection();
pstmt = con.prepareStatement(sql);
pstmt.setInt(1, money);//?에 값 바인딩하기
pstmt.setString(2,memberId );
int resultSize = pstmt.executeUpdate();//데이터변경 //동시에 영향받은 줄 수를 반환받을 수 있다. 100줄변경시 100반환
log.info("resultSize={}", resultSize);
} catch (SQLException e) {
log.error("db error", e);
throw e;
} finally {
close(con, pstmt, null); //다 끝나면 닫아줘야한다.
}
}
public void delete(String memberId) throws SQLException {
String sql = "delete from member where member_id=?";
Connection con =null;
PreparedStatement pstmt = null;
try {
con = getConnection();
pstmt = con.prepareStatement(sql);
pstmt.setString(1,memberId );
pstmt.executeUpdate();//데이터변경 //동시에 영향받은 줄 수를 반환받을 수 있다. 100줄변경시 100반환
} catch (SQLException e) {
log.error("db error", e);
throw e;
} finally {
close(con, pstmt, null); //다 끝나면 닫아줘야한다.
}
}
//Statement는 sql을 그대로 넣는거고 prepareStatement는 파라미터 바인딩이 가능. 기능더많음
//prepareStatement는 Statement를 상속받음
//닫는 메소드, 생성과 반대로 역순으로
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();
}
}
요약하자면 데이터베이스와 연결을 위해 connection객체를 가져와야한다. 연결에 필요한 연결객체라 보면 편할 것 같다.
그리고 그녀석이 prepareStatement객체를 생성한다. 그 놈은 컴파일 된 sql문을 사용하고, 동적으로 값을 설정할 수 있다.
prepareStatement객체는 위 코드에서 쿼리에 값을 바인딩하고 그걸로 데이터를 조회하거나 변경한다.
조회같은 경우 결과값을 resultset객체로 반환하고 우리는 그것을 활용해 원하는 member객체를 조회할 수 있다. 변경의 경우는 영향받은 줄 수를 int로 반환한다.
그리고 연결을 닫아줘야한다. 여기서 중요한 것을 역순으로 해야한다. 그러므로 가장 먼저 호출된 Connection객체를 가장 나중에 닫아준다.
나는 h2데이터베이스와 연결하기 위해 Connection객체가 필요해 DriverManager를 통해 h2드라이버로부터 h2커넥션객체를 얻어올 수 있었고 그것으로 데이터베이스와 연결을 해 원하는 작업을 할 수 있었던 것이다.
DriverManager 는 라이브러리에 등록된 드라이버 목록을 자동으로 인식한다. 이 드라이버들에게 순서대로 다음 정보를 넘겨서 커넥션을 획득할 수 있는지 확인한다.
여기서 각각의 드라이버는 URL 정보를 체크해서 본인이 처리할 수 있는 요청인지 확인한다. 예를 들어서 URL이 jdbc:h2 로 시작하면 이것은 h2 데이터베이스에 접근하기 위한 규칙이다. 따라서 H2 드라이버는 본인이 처리할 수 있으므로 실제 데이터베이스에 연결해서 커넥션을 획득하고 이 커넥션을 클라이언트에 반환한다
참조
https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-db-1
'JDBC' 카테고리의 다른 글
DataSource사용하기 (1) | 2024.01.30 |
---|---|
커넥션 풀 (0) | 2024.01.30 |