들어가며
- 저번 포스트에서는 데이터를 저장하는 기능을 JDBC를 사용하여 구현하였다.
- 이번 포스트에서는 저장된 데이터를 조회하는 기능을 JDBC를 사용하여 구현해본다.
데이터의 조회 구현
- 데이터를 조회하는 SQL 구문은 다음과 같다.
SELECT * FROM MEMBER WHERE MEMBER_ID=?
- JDBC를 사용하여 데이터를 조회하기 위해서는 해당 SQL 구문을 DB에 전송할 커넥션이 필요하다.
- 또한 해당 SQL을 전송시킬 Statement도 필요하다.
- 그리고 조회한 데이터를 가져올 객체인 ResultSet이라는 객체 역시 필요하다.
public Member findById(String memberId) throws SQLException{
String sql = "select * from member where member_id=?";
Connection conn = null;
PrepareStatement pstmt = null;
ResultSet rs = null;
try{
conn = getConnection();
pstmt = conn.prepareStatement(sql);
pstmt.setString(1, memberId);
rs = pstmt.excuteQuery();
if(rs.next()){
Member member = new Member();
member.setMemberId(rs.getString("member_id"));
member.setMoney(rs.getInt("money"));
} else{
throw new NoSuchElementException("member not found, memberId = " + memberId);
}
return member;
} catch (SQLException e){
throw e;
} finally{
close(conn, pstmt, rs);
}
}
- close()와 getConnection()의 경우 이후 전체 코드에서 볼 수 있다. 또는 이전 포스트에서도 볼 수 있다.
- 이 findById 메서드는 다음과 같은 순서로 동작한다.
- getConnection()을 통해 커넥션을 연결하고, sql을 전송한다.
- sql로 인한 연산 결과는 ResultSet이라는 데이터 구조에 저장되는데 ResultSet에서는 Cursor라는 것을 이용하여 그 다음 데이터를 조회할 수 있다.
- 맨 처음 커서는 아무곳도 가리키고 있지 않기 때문에 rs.next()를 통해 처음 저장된 데이터를 커서가 가리키도록 한 후에 데이터를 조회한다.
- rs.next() == true 라면 데이터가 존재한다는 의미이다. 반대로 false라면 데이터가 존재하지 않는다는 이야기이다.
- getTypename("column name")을 통해 해당 컬럼에 존재하는 데이터를 어떤 타입으로 가져올지를 지정할 수 있다. 물론 반환값은 해당 컬럼을 지정 타입으로 변환한 이후의 데이터가 반환된다.
- memberId와 money를 모두 가져와 멤버 객체에 매핑한다. 만약 이후에 다른 데이터가 존재한다면 rs.next()를 통해 커서를 다음 행으로 옮긴다.
- 모든 처리가 끝나면 매핑된 맴버 객체를 반환하고 커넥션을 종료한다.
데이터 조회 기능 테스트
- 구현한 데이터 조회 기능이 잘 동작하는지를 테스트해보자. 이전에 구현한 테스트 클래스를 가져올 것이다.
class MemberRepositoryV0Test{
MemberRepositoryV0 memberRepository = new MemberRepositoryV0();
@Test
void crud() throws SQLException{
Member member = new Member("memberA", 10000);
repository.save(member);
Member memberA = repository.findById("memberA");
Assertions.assertThat(memberA).isEqualTo(member);
}
}
- Assertions는 테스트 결과를 검증하는 도구 클래스이다.
- assertThat(something1).isEqualTo(something2)은 something1이 something2와 동일한지를 검증할 때 사용한다. 즉 우리가 findById로 찾아온 memberA 객체와 우리가 저장하기 전에 만든 멤버 객체 member가 동일한지를 검증한다.
- 멤버 클래스를 다시 보도록 하자.
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Member{
private String memberId;
private int money;
}
- 아무것도 없는 상태에서 equals 연산을 수행한다면 보통 두 객체의 주소값이 동일한지를 살핀다. 그런데 롬복의 @Data 어노테이션은 내부에 @EqualsAndHashCode 어노테이션이 존재한다.
- @EqualsAndHashCode 어노테이션은 해당 객체의 해시코드와 두 객체의 값이 동일한지를 판단하는 코드를 자동으로 넣어준다. 따라서 equals을 수행 할 시 memberA와 member의 상태 값(memberId, money)가 동일한지를 판단하는 것으로 변환된다.
- 따라서 해당 테스트가 성공하게 된다.
정리
- 지금까지 데이터의 저장, 조회를 구현하였다. 다음 포스트에서는 데이터의 수정을 구현해보고 동일하게 테스팅해본다.
- 전체적인 코드는 다음과 같다.
public class MemberRepositoryV0{
public Member save(Member member) throws SQLException{
String sql = "insert into member(member_id, money) values(?, ?)";
Connection conn = null;
PreparedStatement pstmt = null;
try{
conn = getConnection();
pstmt = conn.prepareStatement(sql);
pstmt.setString(1, member.getMemberId());
pstmt.setInt(2, member.getMoney());
pstmt.excuteUpdate();
return member;
} catch (SQLException e){
throw e;
} finally{
close(conn, pstmt, null);
}
}
public Member findById(String memberId) throws SQLException{
String sql = "select * from member where member_id=?";
Connection conn = null;
PrepareStatement pstmt = null;
ResultSet rs = null;
try{
conn = getConnection();
pstmt = conn.prepareStatement(sql);
pstmt.setString(1, memberId);
rs = pstmt.excuteQuery();
if(rs.next()){
Member member = new Member();
member.setMemberId(rs.getString("member_id"));
member.setMoney(rs.getInt("money"));
} else{
throw new NoSuchElementException("member not found, memberId = " + memberId);
}
return member;
} catch (SQLException e){
throw e;
} finally{
close(conn, pstmt, rs);
}
}
public void close(Connection conn, Statement stmt, ResultSet rs){
if(rs != null){
try{
rs.close();
} catch(SQLException e){
throw e;
}
}
if(stmt != null){
try{
stmt.close();
} catch(SQLException e){
throw e;
}
}
if(conn != null){
try{
conn.close();
} catch(SQLException e){
throw e;
}
}
}
private Connection getConnection(){
return DBConnectionUtil.getConnection();
}
}
'Spring & JPA > JDBC' 카테고리의 다른 글
JDBC - JDBC 커넥션 풀 - 커넥션 풀의 개념 (0) | 2023.06.05 |
---|---|
JDBC - JDBC 사용 - 3. 데이터 수정과 삭제 (0) | 2023.06.03 |
JDBC - JDBC사용 - 1. 데이터 저장 (0) | 2023.06.03 |
JDBC - JDBC의 이해 - 데이터 접근 기술 (0) | 2023.06.03 |
JDBC - JDBC의 이해 - JDBC의 등장 배경 (0) | 2023.06.03 |