Member
엔티티는 아래와 같이 많은 정보들을 담고있는데, 랭킹페이지를 조회할때마다 해당 페이지의 member들의 모든 정보를 불러온다면, 리소스 낭비가 될것입니다.public class Member {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String email;
private String password;
private String username;
private String gender;
private String job;
private String address;
private Integer age;
private Integer height;
private Integer weight;
private Integer split;
private Integer period;
@Embedded
private MemberActivity memberActivity;
Projection
을 활용하여 , entity 전체를 가져오는 것이아니라 조회 대상을 지정해 원하는 값만 조회하였습니다.select
절에서 어떤 컬럼들을 조회할지 대상을 지정하는 것Tuple
이나 DTO
로 값을 조회 할 수있는데, 이번에는 결과를 DTO로 조회하여 반환하였다.프로퍼티 접근
List<MemberDto> result = queryFactory
.select(Projections.bean(MemberDto.class,
member.username,
member.age))
.from(member)
.fetch();
필드 직접 접근
List<MemberDto> result = queryFactory
.select(Projections.fields(MemberDto.class,
member.username,
member.age))
.from(member)
.fetch();
생성자 사용
List<MemberDto> result = queryFactory
.select(Projections.constructor(MemberDto.class,
member.username,
member.age))
.from(member)
.fetch()
}
@QueryProjection
을 지원하며, DTO도 Q파일로 생성해준다.QueryProjection
은 컴파일러로 타입을 체크할 수 있으므로 가장 안전한 방법이다.@Data
public class MemberDto {
private String username;
private int age;
public MemberDto() {
}
@QueryProjection
public MemberDto(String username, int age) {
this.username = username;
this.age = age;
}
}
private List<Member> searchMember1(String usernameCond, Integer ageCond) {
BooleanBuilder builder = new BooleanBuilder();
if (usernameCond != null) {
builder.and(member.username.eq(usernameCond));
}
if (ageCond != null) {
builder.and(member.age.eq(ageCond));
}
return queryFactory
.selectFrom(member)
.where(builder)
.fetch();
}
private List<Member> searchMember2(String usernameCond, Integer ageCond) {
return queryFactory
.selectFrom(member)
.where(usernameEq(usernameCond), ageEq(ageCond))
.fetch();
}
// BooleanExpression
//username의 값이 존재하면 조건 추가, null or 빈문자("")일 경우 null 반환
private BooleanExpression usernameEq(String usernameCond) {
return usernameCond != null ? member.username.eq(usernameCond) : null;
}
//age의 값이 존재하면 조건 추가, null or 빈문자("")일 경우 null 반환
private BooleanExpression ageEq(Integer ageCond) {
return ageCond != null ? member.age.eq(ageCond) : null;
}
@Getter
public class RankingDto {
private Long memberId;
private String userName;
private String profileImage;
private Integer height;
private Integer weight;
private Double point;
private Integer period;
private Long challengeId;
@QueryProjection
public RankingDto(Long memberId, String userName, String profileImage, Integer height, Integer weight,
Double point, Integer period, Long challengeId) {
this.memberId = memberId;
this.userName = userName;
this.profileImage = profileImage;
this.height = height;
this.weight = weight;
this.point = point;
this.period = period;
this.challengeId = challengeId;
}
public class RankingCondition {
//분할, 키, 몸무게, 경력
private Integer split;
private Integer heightGoe;
private Integer heightLt;
private Integer weightGoe;
private Integer weightLt;
private Integer periodGoe;
private Integer periodLt;
public RankingCondition(Integer split, Integer heightGoe, Integer heightLt, Integer weightGoe,
Integer weightLt, Integer periodGoe, Integer periodLt) {
this.split = split;
this.heightGoe = heightGoe;
this.heightLt = heightLt;
this.weightGoe = weightGoe;
this.weightLt = weightLt;
this.periodGoe = periodGoe;
this.periodLt = periodLt;
}
}
public List<RankingDto> rankingList(RankingCondition condition, Pageable pageable) {
return jpaQueryFactory
.select(new QRankingDto(
member.id,
member.username,
member.profileImage.path,
member.height,
member.weight,
memberActivity.point,
member.period,
member.challenge.id
))
.from(member)
.where(splitEq(condition.getSplit()),
heightGoe(condition.getHeightGoe()),
heightLt(condition.getHeightLt()),
weightGoe(condition.getWeightGoe()),
weightLt(condition.getWeightLt()),
periodGoe(condition.getPeriodGoe()),
periodLt(condition.getPeriodLt()))
// 분할 일치
private BooleanExpression splitEq(Integer split) {
return isEmpty(split) ? null : member.split.eq(split);
}
// 키 이상
private BooleanExpression heightGoe(Integer heightGoe) {
return isEmpty(heightGoe) ? null : member.height.goe(heightGoe);
}
// 키 미만
private BooleanExpression heightLt(Integer heightLt) {
return isEmpty(heightLt) ? null : member.height.lt(heightLt);
}
// 몸무게 이상
private BooleanExpression weightGoe(Integer weightGoe) {
return isEmpty(weightGoe) ? null : member.weight.goe(weightGoe);
}
// 몸무게 미만
private BooleanExpression weightLt(Integer weightLt) {
return isEmpty(weightLt) ? null : member.weight.lt(weightLt);
}
// 경력 이상
private BooleanExpression periodGoe(Integer periodGoe) {
return isEmpty(periodGoe) ? null : member.period.goe(periodGoe);
}
// 경력 미만
private BooleanExpression periodLt(Integer periodLt) {
return isEmpty(periodLt) ? null : member.period.lt(periodLt);
}