필요한 기본 정보를 편리하게 사용하기 위해서 추상 함수 추가
public abstract class ConnectionConst {
public static final String URL = "jdbc:h2:tcp://localhost/~/Jdbc";
public static final String USERNAME = "sa";
public static final String PASSWORD = "1234";
}
실제 DB에 연결하는 코드
@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);
}
}
}
데이터 베이스 연결 테스트
@Slf4j
class DBConnectionUtilTest {
@Test
void connection(){
Connection connection = DBConnectionUtil.getConnection();
Assertions.assertThat(connection).isNotNull();
}
}
주의점
slf4j 어노테이션이 작동이 안될수 있는데 gradle에 설정이 추가로 필요하다.
testAnnotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.projectlombok:lombok'
실행결과
INFO hello.jdbc.connection.DBConnectionUtil -- get Connection=conn0: url=jdbc:h2:tcp://localhost/~/Jdbc user=SA ,class=class org.h2.jdbc.JdbcConnection
--> H2 전용 데이터베이스 드라이버가 제공하는 H2전용 커넥션
JDBC 는 java.sql.Connection 표준 커넥터 인터페이스를 정의
JDBC 를 사용해서 회원 데이터를 데이터베이스의 관리하는 기능을 개발진행.
Member 객체 추가
@Data
@NoArgsConstructor
public class Member {
private String memberId;
private int money;
public Member(String memberId, int money) {
this.memberId = memberId;
this.money = money;
}
}
회원을 등록하는 MemberRepositoryV0 버전 추가 진행
public Member save(Member member) throws SQLException {
String sql = "inset 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();
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();
}
PreparedStatement 의 경우 파라미터 바인딩을 통해서 파라미터를 넣어준다.
SqlInjection 예방 가능
repositoryV0 에 조회하는 코드 추가
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 found MemberId=" + memberId);
}
}catch (SQLException e){
log.error("db error", e);
throw e;
} finally {
close(con,pstmt,rs);
}
}
pstmt.executeQuery()
이 코드의 경우에는 데이터를 조회하기 때문에 executeQuery()를 보내고 결과를 ResultSet 에 담아서 반환
데이터 변경시 에서는 executeUpdate() 사용
ResultSet의 경우 최초의 커서의 경우 데이터를 가리키고 있지 않기 때문에 rs.next()를 최소 한번 호출 해줘야 데이터를 조회할 수있다는 것을 기억하자.
데이터를 꺼내는 방법