JPA/Querydsl
Querydls 동적 쿼리 활용
chanhee01
2023. 8. 13. 17:29
엔티티 및 Dto 설정을 해준 다음에 검색을 하는 동적 쿼리를 테스트가 아니라 실제로 활용해볼 것이다.
@Data
public class MemberTeamDto {
private Long memberId;
private String username;
private int age;
private Long teamId;
private String teamName;
@QueryProjection
public MemberTeamDto(Long memberId, String username, int age, Long teamId, String teamName) {
this.memberId = memberId;
this.username = username;
this.age = age;
this.teamId = teamId;
this.teamName = teamName;
}
}
MemberTeamDto는 select 해서 가지고 올 Dto이다. @QueryProjection을 통해 Q파일을 만들어준다.
@Data
public class MemberCond {
// 회원명, 팀명, 나이(ageGoe, ageLoe)
private String username;
private String teamName;
private Integer ageGoe; // 크거나 같거나
private Integer ageLoe; // 작거나 같거나
}
MemberCond는 where절에서 user의 조건을 맞추는 엔티티이다.
MemberRepository에서의 Querydsl
public List<MemberTeamDto> search(MemberCond condition) {
return queryFactory
.select(new QMemberTeamDto(
member.id,
member.username,
member.age,
team.id,
team.name))
.from(member)
.leftJoin(member.team, team)
.where(
usernameEq(condition.getUsername()),
teamNameEq(condition.getTeamName()),
ageGoe(condition.getAgeGoe()),
ageLoe(condition.getAgeLoe()))
.fetch();
}
private BooleanExpression usernameEq(String username) {
return isEmpty(username) ? null : member.username.eq(username);
}
private BooleanExpression teamNameEq(String teamName) {
return isEmpty(teamName) ? null : team.name.eq(teamName);
}
private BooleanExpression ageGoe(Integer ageGoe) {
return ageGoe == null ? null : member.age.goe(ageGoe);
}
private BooleanExpression ageLoe(Integer ageLoe) {
return ageLoe == null ? null : member.age.loe(ageLoe);
}
이전에 사용했던 where 절에서의 동적 쿼리를 응용해서 쿼리를 작성했다. null이면 조건에 null을 보내고 아니면 where절에 조건을 걸어주는 것이다.
조회용 API 컨트롤러
@Profile("local")
@Component
@RequiredArgsConstructor
public class InitMember {
private final InitMemberService initMemberService;
@PostConstruct
public void init() {
initMemberService.init();
}
@Component
static class InitMemberService {
@PersistenceContext
EntityManager em;
@Transactional
public void init() {
Team teamA = new Team("teamA");
Team teamB = new Team("teamB");
em.persist(teamA);
em.persist(teamB);
for (int i = 0; i < 100; i++) {
Team selectedTeam = i % 2 == 0 ? teamA : teamB;
em.persist(new Member("member" + i, i, selectedTeam));
}
}
}
}
다음과 같이 초기 데이터를 만들고 컨트롤러를 만들어준다.
@GetMapping("v1/members")
public List<MemberTeamDto> searchMemberV1(MemberCond condition) {
return memberJpaRepository.search(condition);
}
파라미터에 조건을 설정해주면 해당하는 데이터들만 select해서 가져와 주는 것을 확인할 수 있다.