스프링/5. 스프링 DB-1

42. JDBC 반복문제 해결

sdafdq 2023. 10. 6. 13:23

우리가 앞서 커넥터 얻어오고, 바인딩하고, 커넥터 반환하고

이런 try catch 이 부분이 리포지토리의 crud 모든 부분에 들어갔다.

 

 

이런 반복 문제를 효과적으로 처리하는 방법은 템플릿 콜백 패턴을 사용하는 것이다.

 

스프링은 이미 JDBC 반복문제를 해결하기 위해 JdbcTemplate를 제공한다.

 

그냥 쓰면 된다.

@Slf4j
public class MemberRepositoryV5 implements MemberRepository{
    private final JdbcTemplate template;

    public MemberRepositoryV5(DataSource dataSource) {
        this.template = new JdbcTemplate(dataSource);
    }

    @Override
    public Member save(Member member){
        String sql = "insert into member(member_id, money) values(?,?)";
        template.update(sql, member.getMemberId(), member.getMoney());
        return member;
    }

    @Override
    public Member findById(String memberId){
        String sql = "select * from member where member_id = ?";
        return template.queryForObject(sql, memberRowMapper(), memberId);
    }

    private RowMapper<Member> memberRowMapper() {
        return (rs, rowNum) ->{
            Member member = new Member();
            member.setMemberId(rs.getString("member_id"));
            member.setMoney(rs.getInt("money"));
            return member;
        };
    }

    @Override
    public void update(String memberId, int money){
        String sql = "update member set money=? where member_id=?";
        template.update(sql, money, memberId);
    }

    @Override
    public void delete(String memberId){
        String sql = "delete from member where member_id=?";
        template.update(sql, memberId);
    }
}

저렇게 그냥 새로 JdbcTemplate에 dataSource가 DB종류에 대한 정보를 가지고 있으니 넣어서 생성해주고,

DB의 뭔가를 update(c,u,d) 하는 것은 템플릿.update(sql, 바인드첫번째, 바인드두번째...) 등으로 한다.

바인드로 들어가는 인자의 순서는 sql 쿼리의 ? 순서와 같다.

 

저렇게 하면 끝이다.

커넥션 얻어오고, 바인딩해주고, 쿼리 날려주고, 커넥션 반환해주고 이거 다 해준다.

 

읽어 오는 것은 

템플릿.query()인 듯 한데,

이번에 사용한 것은 템플릿.queryForObject(sql, 맵퍼, 바인드될요소...) 이다.

직역 그대로 쿼리를 날리는데, 오브젝트를 위한 것이다.

 

중요한 것은 맵퍼인데,

이름 그대로 맵핑해 주는 것이다.

RowMapper는 스프링이 제공해 주는 것이다.

반환할 때 콜백함수로, (아무래도 맵퍼니 뭔가 행동을 해야하는 거라서 콜백함수,) 인자로 rs와 rowNum이 자동으로 들어간다.

rs는 resultSet이다. 보통 select 해서 결과를 가져오면 저 set에 담긴다.

 

그렇게 DB에서 member_id에 ?에 맨 처음 findById에서 인자로 받은 memberId를 넣고,

template.queryForObject(sql, memberRowMapper(), memberId);

하면은 sql의 ?에 memberId가 바인딩 되어서 먼저 쿼리를 날려주고,

그것의 결과가 두번째 인자인 맵퍼로 가게된다.

 

거기서 새 멤버를 생성해서, DB에서 반환받은 값을 토대로 멤버를 완전히 완성시켜 주고, 그 멤버를 반환해준다.