DB 에 있는 @ElementCollection 으로 묶어준 데이터를 프론트로 보내야 하는 일이 생겼다. 객체로 보낼 수도 있지만 그 객체 안에 담겨있는 id 값을 다시 사용하기 위해서는 배열로 보내는 편이 훨씬 낫다.
일단 원본은 User 엔티티에서 VO(값 객체) 타입으로 되어 있는 Set 배열 데이터이다.
// User Entity
@ElementCollection
private Set<WishContentId> wishContentIds = new HashSet<>();
@ElementCollection
private Set<WatchedContentId> watchedContentIds = new HashSet<>();
@ElementCollection
private Set<FavoriteContentId> favoriteContentIds = new HashSet<>();
프론트에서 특정 유저 아이디를 넘겨주면, 서버에서는 그 아이디를 통해 JPA Repository 를 조회한다. 그리고 다시 프론트로 유저의 데이터를 보내주는데 이 때 DTO 에 담아서 반환한다. 이 때 DTO 에서 VO 타입을 Long 형의 Wrapper 클래스로 변환해주는 것이다.
코드는 아래와 같다.
public class UserDto {
private Long id;
private Set<Long> wishContentIds; // 변환한 데이터를 받을 필드 변수
public UserDto(Long id, Set<WishContentId> wishContentIds) {
this.id = id;
setWishContentIds(wishContentIds); // 값객체 변환해주는 메서드
}
private void setWishContentIds(Set<WishContentId> wishContentIds) {
this.wishContentIds = wishContentIds
.stream()
.map(WishContentId::getValue)
.collect(Collectors.toSet());
}
생성자에서 VO 타입으로 되어 있는 파라미터를 setWishContentIds 라는 메서드의 인자값으로 받는다. 그 메서드는 Set<Long> 타입으로 되어 있는 필드 변수에 값 객체 형태의 파라미터를 대입해 주는 역할을 한다.
Long 타입으로 변환하기 위해서는 당연히 값 객체의 value 값을 Long 형으로 해놓아야 한다.
// WishContentId
@Embeddable
public class WishContentId {
@Column(name = "wish_content_id")
private Long value;
public WishContentId() {
}
public WishContentId(Long value) {
this.value = value;
}
public Long getValue() {
return value;
}
그리고 프론트로 보낸 특정 유저가 가진 배열 데이터를 어떻게 서버로 다시 받을 지 고민하고 있었는데 동기분께서 배열을 String 형태로 만든 후 받아서 split 한 후에 id 값을 사용하면 된다는 조언을 주셔서 시도해 보았는데 아주 잘 동작하였고 방법은 아래와 같다.
프론트에서 배열 데이터를 join() 메서드를 활용해 String 형태로 만든 후 서버로 보내면 서버에서는 @RequestParam 으로 String 데이터를 받아서 사용하는 것이다.
// 프론트에서 보낸 문자열 id 값
const wishContentId = wishContentIds?.join(',');
// 서버에서 받은 문자열을 split 해서 사용
public UserProfileContentsDto wishContents(Long userId, String wishContentId) {
String[] contentIds = wishContentId.split(",");
List<UserProfileContentDto> contentDtos = Arrays.stream(contentIds)
.map(contentId -> {
User user = userRepository.findById(userId)
.orElseThrow(() -> new UserNotFound());
Content content = contentRepository.findByTmdbId(Long.parseLong(contentId))
.orElseThrow(() -> new ContentNotFound());
return new UserProfileContentDto(
user.getId(),
content.getTmdbId(),
content.getImageUrl(),
content.getKorTitle());
}).toList();
return new UserProfileContentsDto(contentDtos);
}
'TIL' 카테고리의 다른 글
Plmography 프로젝트 작업 로그 #44 - JPA 에서 상위 n 개 데이터 찾을 때 (23.02.03 TIL) (1) | 2023.02.03 |
---|---|
Plmography 프로젝트 작업 로그 #43 - 기획의 중요성 (23.02.02 TIL) (0) | 2023.02.02 |
Plmography 프로젝트 작업 로그 #41 - JPQL 에서 exists 문법 사용하기 (23.01.31 TIL) (0) | 2023.01.31 |
Plmography 프로젝트 작업 로그 #40 - 탐색 페이지 필터링 구현 (23.01.30 TIL) (0) | 2023.01.30 |
Plmography 프로젝트 작업 로그 #39 - 비즈니스 로직 테스트 코드는 확실하게! (23.01.20 TIL) (0) | 2023.01.20 |
댓글