스프링데이터 + JPA/QueryDSL 38

37. Querydsl 리포지토리 지원

이거는, Querydsl을 사용한 리포지토리를 만들 때, 상속받아서 쓰면 약간 편리한? 그런 거다. @Repository public abstract class QuerydslRepositorySupport { private final PathBuilder builder; private @Nullable EntityManager entityManager; private @Nullable Querydsl querydsl; public QuerydslRepositorySupport(Class domainClass) { Assert.notNull(domainClass, "Domain class must not be null"); this.builder = new PathBuilderFactory().creat..

36. Querydsl Web 지원

스프링 데이터가 제공하는 QueryDSL이 컨트롤러에서 술어를 인자로 받을 수 있는 기능. 이거는 우선 단순한 조건만 가능 조건도 거의 eq정도만 됨. 컨트롤러가 Querydsl에 의존. join도 어려움 조건을 조금 복잡하게 하려면 오히려 바인딩 해 주는게 더 복잡함. 저 QuerydslBinderCustomizer 상속받은 다음, 저렇게 바인딩 해 줘야 함. 쓰지 마셈.. 지금은. 술어를 클라이언트 파라미터로 받을 수 있는 것은 좋으나, 그에 따라 컨트롤러가 QueryDSL 기능에 의존하게 되고, 쓸 수 있는 기능에 비해 번거로움

35. 스프링 데이터 JPA가 제동하는 QueryDSL 기능

사실 지금부터 이야기 하는 기능들은, 제약이 커서 실무에서는 잘 활용 안함. 테이블 하나일 땐 괜찮은 데 join 하면서 여러 개 하면 잘 동작을 안한다고 함. 우선 첫번째로는, QuerydslPredicateExecutor라고, 스프링 데이터 JPA에서 Querydsl과 함께 쓸 수 있도록 해주는 것 이다. 그러니까, 마치 우리가 스프링 데이터 JPA 만들었을 때 처럼, findAll 같은 것을 지원해 주는 것이다. 그런데, 거기 안에 술어를 쓸 수 있다. public interface MemberRepository extends JpaRepository, MemberRepositoryCustom, QuerydslPredicateExecutor { List findByUsername(String use..

34. QueryDSL 페이지 컨트롤러

@GetMapping("/v3/members") public Page searchMemberV3(MemberSearchCondition condition, Pageable pageable){ return memberRepository.searchPageComplex(condition,pageable); } 여기서 볼 점은, Pageable 인자 정도? 참고로, ArgumentsResolver에 의해서, 알아서 저 객체들에 다 바인딩 해 준다. 객체의 필드명과, 클라이언트가 요청할 때 보내는 파라미터명이 같아야 바인딩이 제대로 된다. Pageable의 인자로는 page : 몇번째 페이지 size : 한 페이지 당 사이즈 가 있다. 예를 들어 http://localhost:8080/v3/members?pag..

33. 스프링 데이터 JPA 페이징 활용. QueryDSL 페이징 연동

먼저, 간단하게 QueryDSL에서 제공해 주는 기능. @Override public Page searchPageSimple(MemberSearchCondition condition, Pageable pageable) { QueryResults result = query.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()), age..

32. 사용자 정의 리포지토리

https://qwefdg3.tistory.com/889 앞서 배웠던 여기에 쿼리DSL을 쓸 것 public interface MemberRepositoryCustom { List search(MemberSearchCondition condition); } 이름 적당히 해서 인터페이스 만들고, 구현할 메소드 선언 해 주고 public class MemberRepositoryImpl implements MemberRepositoryCustom{ private final JPAQueryFactory query; public MemberRepositoryImpl(EntityManager em) { this.query = new JPAQueryFactory(em); } @Override public List s..

30. 조회 API 컨트롤러 만들기

컨트롤러 자체 만드는 건 쉽다 @RestController @RequiredArgsConstructor public class MemberController { private final MemberJpaRepository memberJpaRepository; @GetMapping("/v1/members") public List searchMemberV1(MemberSearchCondition condition){ return memberJpaRepository.search(condition); } } 이렇게. 그냥 condition하면 저거는 이제 setter로 자동으로 알아서 클라이언트에서 들어오는 파라미터의 변수명만 잘 맞는다면 알아서 들어간다. 리포지토리로 먼저 정의해뒀던 search public ..

29. 동적쿼리 성능 최적화 조회 Where절 사용.

과거 우리가 where절은 ,로 구분하여, 여러 표현식을 인자로 주면 그게 and로 묶인다고 했다. https://qwefdg3.tistory.com/937 그래서, 표현식을 만들어 where절 안에 인자로 주면, 그게 알아서 여러 개면 and로 묶여 쿼리를 만들어 준다. 그렇기에, private BooleanExpression usernameEq(String username){ return StringUtils.hasText(username) ? member.username.eq(username) : null; } private BooleanExpression teamNameEq(String teamName){ return StringUtils.hasText(teamName) ? team.name.eq..

28. 동적 쿼리와 성능 최적화 조회, Builder

public List searchByBuilder(MemberSearchCondition condition){ BooleanBuilder builder = new BooleanBuilder(); if (StringUtils.hasText(condition.getUsername())) { builder.and(member.username.eq(condition.getUsername())); } if (StringUtils.hasText(condition.getTeamName())) { builder.and(team.name.eq(condition.getTeamName())); } if(condition.getAgeGoe() != null){ builder.and(member.age.goe(condition..