
상황
현재 User의 Rank와 방 목록을 조회하는 API에서 findAll 로직을 구현하고 있다.
User Rank로 예시를 들어보려고 한다.
public List<UserRankDto> getUserRanks() {
List<User> users = em.createQuery("SELECT u FROM User u ORDER BY u.score DESC", User.class)
.getResultList();
return users.stream()
.map(UserRankDto::new)
.collect(Collectors.toList());
}
현재 이 코드는 JPQL을 사용하여 User의 Score를 기준으로 내림차순으로 List를 뽑았고 이 User 객체를 UserRankDto로 매핑해서 반환한다.
@Getter
public class UserRankDto {
private String nickname;
private int score;
public UserRankDto(User user) {
this.nickname = user.getNickname();
this.score = user.getScore();
}
}
이렇게 구성되어있다. 직접 생성자를 추가해주었다.
💡 Java에서는 클래스에 생성자가 정의되어 있을 때만 해당 클래스를 생성자 참조 :: 로 사용할 수 있다.
따라서 UserRankDto 클래스에는 파라미터가 없는 생성자를 추가해야 한다.
해당 생성자를 제거할 시 아래와 같은 에러를 확인할 수 있다.
error: incompatible types: invalid constructor reference
.map(UserRankDto::new)
^
constructor UserRankDto in class UserRankDto cannot be applied to given types
required: no arguments
found: User
reason: actual and formal argument lists differ in len.....
결론부터 말하자면 불가능하다.
왜냐하면 현재 저 생성자는 User를 파라미터로 받아와서 User에서 반환할 Dto 내의 값들을 기록하고 있다.
public class UserRankDto {
private String nickname;
private int score;
public UserRankDto(String nickname, int score) {
this.nickname = user.getNickname();
this.score = user.getScore();
}
}
@AllArgsConstructor를 사용하면 이러한 생성자가 만들어지니 DB에서 가져온 User를 매핑할 때 사용할 수 없다.
결론적으로 stream 메서드만을 사용할 때 나는 @Getter 어노테이션 하나만 사용하였다.
틀린 사실이 있거나 추가적으로 알면 좋은 내용이 있으시다면 언제든지 댓글 부탁드립니다!