article thumbnail image
Published 2022. 8. 1. 21:04

MemberRepositoryV0 - 회원 조회 추가

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);
    }
}

 

 

findById() - 쿼리 실행

  1. sql : 데이터 조회를 위한 select SQL을 준비한다.
  2. rs = pstmt.executeQuery() 데이터를 변경할 때는 executeUpdate() 를 사용하지만, 데이터를 조회할 때는 executeQuery() 를 사용한다. executeQuery() 는 결과를 ResultSet 에 담아서 반환한다.

 

 

 

ResultSet

 

ResultSet 은 다음과 같이 생긴 데이터 구조이다. 보통 select 쿼리의 결과가 순서대로 들어간다. 

  • 예를 들어서 select member_id, money 라고 지정하면 member_id , money 라는 이름으로 데이터가 저장된다.
    참고로 select * 을 사용하면 테이블의 모든 컬럼을 다 지정한다.

ResultSet 내부에 있는 커서( cursor )를 이동해서 다음 데이터를 조회할 수 있다.
rs.next() : 이것을 호출하면 커서가 다음으로 이동한다. 참고로 최초의 커서는 데이터를 가리키고 있지 않기 때문에 rs.next() 를 최초 한번은 호출해야 데이터를 조회할 수 있다.

  • rs.next() 의 결과가 true 면 커서의 이동 결과 데이터가 있다는 뜻이다.
  • rs.next() 의 결과가 false 면 더이상 커서가 가리키는 데이터가 없다는 뜻이다.

rs.getString("member_id") : 현재 커서가 가리키고 있는 위치의 member_id 데이터를 String 타입으로 반환한다.
rs.getInt("money") : 현재 커서가 가리키고 있는 위치의 money 데이터를 int 타입으로 반환한다.

 

 

ResultSet 결과 예시

참고로 이 ResultSet 의 결과 예시는 회원이 2명 조회되는 경우이다.

 

1-1 에서 rs.next() 를 호출한다.
1-2 의 결과로 cursor 가 다음으로 이동한다. 이 경우 cursor 가 가리키는 데이터가 있으므로 true 를 반환한다.


2-1 에서 rs.next() 를 호출한다.
2-2 의 결과로 cursor 가 다음으로 이동한다. 이 경우 cursor 가 가리키는 데이터가 있으므로 true 를 반환한다.


3-1 에서 rs.next() 를 호출한다.
3-2 의 결과로 cursor 가 다음으로 이동한다. 이 경우 cursor 가 가리키는 데이터가 없으므로 false 를 반환한다.

 

 

findById() 에서는 회원 하나를 조회하는 것이 목적이다. 따라서 조회 결과가 항상 1건이므로 while 대신에 if 를 사용한다. 다음 SQL을 보면 PK인 member_id 를 항상 지정하는 것을 확인할 수 있다.
SQL: select * from member where member_id = ?

 

 

MemberRepositoryV0Test - 회원 조회 추가

package hello.jdbc.connection.repository;

import hello.jdbc.connection.domain.Member;
import lombok.extern.slf4j.Slf4j;
import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.Test;

import java.sql.SQLException;

import static org.assertj.core.api.Assertions.*;
import static org.junit.jupiter.api.Assertions.*;

@Slf4j
class MemberRepositoryV0Test {

    MemberRepositoryV0 repository = new MemberRepositoryV0();

    @Test
    void crud() throws SQLException {
        Member member = new Member("memberV0", 10000);
        repository.save(member);

        Member findMember = repository.findById(member.getMemberId());
        log.info("findMember={}", findMember);
        log.info("member == findMember {}", member == findMember);
        log.info("member equals findMember {}", member.equals(findMember));
        assertThat(findMember).isEqualTo(member);
    }

}

 

 

실행 결과

MemberRepositoryV0Test - findMember=Member(memberId=memberV0, money=10000)

회원을 등록하고 그 결과를 바로 조회해서 확인해보았다.


참고로 실행 결과에 member 객체의 참조 값이 아니라 실제 데이터가 보이는 이유는 롬복의 @DatatoString() 을 적절히 오버라이딩 해서 보여주기 때문이다. isEqualTo() : findMember.equals(member) 를 비교한다. 결과가 참인 이유는 롬복의 @Data 는 해당 객체의 모든 필드를 사용하도록 equals() 를 오버라이딩 하기 때문이다

 

 

 

 

출처 : 김영환 스프링 DB 강의

'JDBC' 카테고리의 다른 글

커넥션 풀 이해  (0) 2022.08.02
JDBC 개발 - 수정, 삭제  (0) 2022.08.01
JDBC 개발 - 등록  (0) 2022.08.01
데이터베이스 연결  (0) 2022.08.01
JDBC와 최신 데이터 접근 기술  (0) 2022.08.01
복사했습니다!