Spring
JDBC Template을 이용한 회원정보 조회 기능 구현(2)
snape
2023. 2. 23. 09:01
계속해서 SNS 프로젝트를 진행해보자.
이번에는 조회 기능을 구현하도록 하겠다.
DTO
추후 JPA로 변환 했을 때, Member 객체를 controller까지 직접 사용하게 된다면 OSIV(Open Session In View)와 같은 문제가 생길 수 있다.
또한 entity가 의도치 않게 변경될 가능성이 생기고 불필요한 정보들까지 내어주게 된다.
따라서 DTO를 사용하여 위의 문제를 예방하도록 한다.
public record MemberDto(
Long id,
String email,
String nickname,
LocalDate birthday
) {
}
Repository
public Optional<Member> findById(Long id) {
var sql = String.format("SELECT * FROM %s WHERE id = :id", TABLE);
var param = new MapSqlParameterSource()
.addValue("id", id);
RowMapper<Member> rowMapper = (ResultSet resultSet, int rowNum) -> Member
.builder()
.id(resultSet.getLong("id"))
.email(resultSet.getString("email"))
.nickname(resultSet.getString("nickname"))
.birthDay(resultSet.getObject("birthday", LocalDate.class))
.createdAt(resultSet.getObject("createdAt", LocalDateTime.class))
.build();
var member = namedParameterJdbcTemplate.queryForObject(sql, param, rowMapper);
return Optional.ofNullable(member);
}
BeanPropertyRowMapper를사용하지 않고 RowMapper를 직접 구현한 이유는 Setter를 막기 위해서다.
Setter를 열어놓게 되면 어디서든 Member에 대해 수정이 일어날 수 있기 떄문에, 코드가 많아지거나 하면 side effect 측정이 힘들어진다.
따라서 웬만하면 setter를 직접 여는 것보다, 의미 있는 동작 단위로 묶어서 개발 하는 것이 좋다.
Service
@Service
@RequiredArgsConstructor
public class MemberReadService {
private final MemberRepository memberRepository;
public MemberDto getMember(Long id) {
var member = memberRepository.findById(id).orElseThrow();
return toDto(member);
}
public MemberDto toDto(Member member) {
return new MemberDto(member.getId(), member.getEmail(), member.getNickname(), member.getBirthDay());
}
}
Contoller
@GetMapping("/members/{id}")
public MemberDto getMember(@PathVariable Long id) {
return memberReadService.getMember(id);
}