서버와 데이터베이스를 연결하는 방법에 대해서 공부했다.
사용된 데이터베이스 : H2
데이터베이스에 접근하기위해 필요한 정보들을 상수로 만들어 관리
package hello.jdbc.connection;
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 = "";
}
데이터베이스에 연결하려면 JDBC가 제공하는 DriverManager.getConnection(..) 을 사용하면 된다.
이렇게 하면 라이브러리에서 데이터베이스 드라이버를 찾아서 해당 드라이버가 제공하는 커넥션을 반환해준다.
package hello.jdbc.connection;
import lombok.extern.slf4j.Slf4j;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import static hello.jdbc.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);
}
}
}
JDBC DriverManager
JDBC가 제공하는 DriverManager는 라이브러리에 등록된 DB 드라이버들을 관리하고, 커넥션을 획득하는 기능을 제공한다.
DB커넥션과 관련된 URL을 체크하여 URL이 jdbc:h2로 시작하면 H2드라이버가 데이터베이스에 연결해서 커넥션을 획득한다.
만약 jdbc:mysql이면 MySQL드라이버가 해당 커넥션을 획득하는 방식이다.
JDBC개발 - 등록
package hello.jdbc.repository;
import hello.jdbc.connection.DBConnectionUtil;
import hello.jdbc.domain.Member;
import lombok.extern.slf4j.Slf4j;
import java.sql.*;
import static hello.jdbc.connection.DBConnectionUtil.getConnection;
@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(); //Statement를 통해 SQL커넥션을 이용하여 실제 데이터베이스에 전달한다.
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) throws SQLException {
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() { //DBConnectionUtil클래스의 DB 커넥션 메서드 활용
return DBConnectionUtil.getConnection();
}
}
con.prepareStatement(sql) : 데이터베이스에 전달할 SQL과 파라미터로 전달할 데이터들을 준비한다.
pstmt.setString(1, member.getMemberId()) ==> SQL의 첫번째 ? 에 값을 지정한다.
pstmt.setInt(2, member.getMoney()) ==> SQL의 두번째 ? 에 값을 지정한다.
*주의*
쿼리를 실행하고 나서 Connection과 PreparedStatement를 정리 해줘야 한다.
정리 해주지 않으면 커넥션이 끊어지지 않고 계속 유지가 되어서 문제가 발생할 수 있다.
<테스트 코드>
package hello.jdbc.repository;
import hello.jdbc.domain.Member;
import org.junit.jupiter.api.Test;
import java.sql.SQLException;
class MemberRepositoryV0Test {
MemberRepositoryV0 repository = new MemberRepositoryV0();
@Test
void crud() throws SQLException {
Member member=new Member("memberV0",10000);
repository.save(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();
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 fond memberId="+memberId);
}
}catch (SQLException e){
log.error("db error",e);
throw e;
}finally {
close(con,pstmt,rs);
}
}
sql : 데이터 조회를 위한 select SQL을 준비한다.
rs = pstmt.executeQuery() 데이터를 조회 할 때는 executeQuery() 데이터를 변경할 때는 를 사용한다.
데이터를 변경할때는 executeUpdate() 를 사용한다.
rs.next() : resultSet에서 최초의 커서는 아무것도 가리키고 있지 않기 때문에 rs.next()를 한번 호출 해줘야 한다.
rs.next() 가 true이면 ==> 커서 이동결과 데이터가 있다는 뜻
rs.next()가 false이면 ==> 커서 이동결과 데이터가 없다는 뜻
<테스트 코드>
@Test
void crud() throws SQLException {
Member member=new Member("memberV2",10000);
repository.save(member);
//findById
Member findMember = repository.findById(member.getMemberId());
log.info("findMember={}",findMember);
Assertions.assertThat(findMember).isEqualTo(member);
}
실행결과
수정
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();
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();
}catch (SQLException e) {
log.error("db error", e);
throw e;
}finally {
close(con, pstmt, null);
}
}
<테스트 코드>
package hello.jdbc.repository;
import hello.jdbc.domain.Member;
import lombok.extern.slf4j.Slf4j;
import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.Test;
import java.sql.SQLException;
import java.util.NoSuchElementException;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
@Slf4j
class MemberRepositoryV0Test {
MemberRepositoryV0 repository = new MemberRepositoryV0();
@Test
void crud() throws SQLException {
Member member=new Member("memberV4",10000);
repository.save(member);
//findById
Member findMember = repository.findById(member.getMemberId());
log.info("findMember={}",findMember);
assertThat(findMember).isEqualTo(member);
//update: money: 10000 -> 20000
repository.update(member.getMemberId(), 20000);
Member updatedMember = repository.findById(member.getMemberId());
assertThat(updatedMember.getMoney()).isEqualTo(20000);
//delete
repository.delete(member.getMemberId());
assertThatThrownBy(() -> repository.findById(member.getMemberId()))
.isInstanceOf(NoSuchElementException.class);
}
}
<테스트 결과>
'BackEnd > Database' 카테고리의 다른 글
스프링 예외 추상화 (0) | 2025.02.04 |
---|---|
TransactionTemplate (0) | 2025.02.01 |
DB 락 (0) | 2025.01.19 |
커넥션 풀 / DataSource (0) | 2025.01.13 |
JDBC란 무엇인가 (0) | 2025.01.11 |