2022. 10. 18. 14:45ใ์ธํ๋ฐ/์ค์ ! QueryDSL
https://www.inflearn.com/course/Querydsl-%EC%8B%A4%EC%A0%84/dashboard
ํด๋น ๊ฐ์๋ฅผ ๋ฃ๊ณ ์ ๋ฆฌํ ๋ด์ฉ์ ๋๋ค. ๐๐๐ฅฐ
โ ์ด๋ฒ ๊ฐ์์์๋ ์คํ๋ง ๋ฐ์ดํฐ JPA๊ฐ ์ ๊ณตํ๋ Querydsl ๊ธฐ๋ฅ์ ๋ํด์ ์๊ฐํ๋๋ฐ ์ฌ๊ธฐ์ ์๊ฐํ๋ ๊ธฐ๋ฅ๋ค์ ๋จ์ํ ๊ฒฝ์ฐ์๋ ํธํ์ง๋ง ์ ์ฝ์ด ์ปค์ ๋ณต์กํ ์ค๋ฌด ํ๊ฒฝ์์ ์ฌ์ฉํ๊ธฐ์๋ ๋ง์ด ๋ถ์กฑํ ํธ์ด๋ผ๊ณ ํ๋ค.
๊ทธ๋ผ์๋ ์ผ๋จ ์คํ๋ง ๋ฐ์ดํฐ์์ ์ ๊ณตํ๋ ๊ธฐ๋ฅ์ด๊ธฐ ๋๋ฌธ์ ๊ฐ๋จํ ์๊ฐํ๊ณ ์ ๋ถ์กฑํ์ง ์ค๋ช ํด์ค๋ค๊ณ ํ๋ค.
1๏ธโฃ ์ธํฐํ์ด์ค ์ง์ - QuerydslPredicateExecutor
- ๊ณต์ url
https://docs.spring.io/spring-data/jpa/docs/2.2.3.RELEASE/reference/html/ #core.extensions.querydsl
QuerydslPredicateExecutor ์ธํฐํ์ด์ค
๋ฆฌํฌ์งํ ๋ฆฌ์ ์ ์ฉ
MemberRepository
๋์ ํ์ธ
MemberRepositoryTest
์ฌ์ฉํ ๋ ๋ณด๋ฉด
memberRepository.findAll(member.age.between(10, 40).and(member.username.eq("member1"));
์ด๋ ๊ฒ ์ง์ ํด์ฃผ๋ฉด
์ง์ ํ ์กฐ๊ฑด์ ๋ง๊ฒ ์ฟผ๋ฆฌ๊ฐ ํธ์ถ๋๋ ๊ฒ์ ํ์ธํ ์ ์๋ค.
โญ ํ๊ณ์ โญ
- ์กฐ์ธ์ ํ ์ ์๋ค.(๋ฌต์์ ์กฐ์ธ์ ๊ฐ๋ฅํ์ง๋ง left join์ด ๋ถ๊ฐ๋ฅํ๋ค.)
- ํด๋ผ์ด์ธํธ๊ฐ Querydsl์ ์์กดํด์ผ ํ๋ค. ์ฆ, ์๋น์ค ํด๋์ค๊ฐ Querydsl์ด๋ผ๋ ๊ตฌํ ๊ธฐ์ ์ ์์กดํด์ผ ํ๋ค.
- ๋ณต์กํ ์ค๋ฌดํ๊ฒฝ์์ ์ฌ์ฉํ๊ธฐ์๋ ํ๊ณ๊ฐ ๋ช ํํ๋ค.
left join์ด ์๋๋ฉด ์ค๋ฌด์์ ๊ฑฐ์ ์ฌ์ฉํ๊ธฐ ํ๋ค๊ณ ... ๋จ์ ํ ์ด๋ธ ํ๋๊ฐ์ง๊ณ ๋ง ํ ๋ ์ ๋๋ง ์ฌ์ฉํ ์ ์๋ค..
ํ๊ณ๊ฐ ๋ช ํํจ..! ์ฌ์ฉ ๊ถ์ฅํ์ง ์์
โ ์ฐธ๊ณ ๋ก QuerydslPredicateExecutor๋ Pageable, Sort๋ฅผ ๋ชจ๋ ์ง์ํ๊ณ ์ ์ ๋์ํ๋ค.
2๏ธโฃ Querydsl Web ์ง์
๊ณต์ url: https://docs.spring.io/spring-data/jpa/docs/2.2.3.RELEASE/reference/html/#core.web.type-safe
์ด๋ฐ์์ผ๋ก ํ๋ผ๋ฏธํฐ์ ์ง์ ํด์ฃผ๋ฉด
์ด๋ ๊ฒ ์ฟผ๋ฆฌ ์คํธ๋ง์ ์ฃผ๋ฉด
์ด๋ฐ์์ผ๋ก ๋ฐ๊ฟ์ค๋ค๋ ๋ง์ด๋ค.
-> ์ด๊ฑด ๊ฐ์์์ ์ฝ๋๋ ์์ฑ์ํ๊ณ ๊ณต์ url๋ง ๋ณด๊ณ ๋์ด๊ฐ๊ฑด๋ฐ ๊ทธ์ ๋๋ก ์ฌ์ฉ ๊ถ์ฅ์ ์์ ํ์ง ์๋๋ค๋ ๊ฒ์ด๋ค..!
๊ฐ์์์ ์ฝ๋๋ ์์ด ์ค๋ช ํ๋๊ฑด ์ด๊ฒ ๊ฑฐ์ ์ฒ์์ด์๋๊ฑฐ ๊ฐ๋ค ใ ใ ใ ๊ทธ๋งํผ ์์ค์ํ๋ค๋ ๊ฑฐ๊ฒ ์ง~~
โญ ํ๊ณ์ โญ
- ๋จ์ํ ์กฐ๊ฑด๋ง ๊ฐ๋ฅ
- ์กฐ๊ฑด์ ์ปค์คํ ํ๋ ๊ธฐ๋ฅ์ด ๋ณต์กํ๊ณ ๋ช ์์ ์ด์ง ์์
- ์ปจํธ๋กค๋ฌ๊ฐ Querydsl์ ์์กด
- ๋ณต์กํ ์ค๋ฌดํ๊ฒฝ์์ ์ฌ์ฉํ๊ธฐ์๋ ํ๊ณ๊ฐ ๋ช ํ
๋จ์ํ ์กฐ๊ฑด์ด ๊ฑฐ์ eq, in, contains ์ ๋๊ฐ ์๊ณ , ๊ฑฐ์ ์ด์ ๋๋ง ์ฌ์ฉํ๋ค๊ณ ํ๋ค.
๊ทธ๋ฆฌ๊ณ ์ปจํธ๋กค๋ฌ๊ฐ Querydsl์ ์์กดํ๋๊ฒ ํ๊ณ์ ์ธ ์ด์ ๋ ํด๋ผ์ด์ธํธ๊ฐ Querydsl์ ์์กดํ๊ฒ ๋๋ฉด ๋์ค์ ๊ตฌํ ๊ธฐ์ ์ ๋ฐ๊พธ๊ฒ ๋๋ฉด ์ ์ฒด๋ฅผ ๋ค ๋ฐ๊ฟ์ค์ผ ํ๊ธฐ ๋๋ฌธ์ ์ ์ง๋ณด์ ์ธก๋ฉด์์ ์์ข์ ์ ์๊ธฐ ๋๋ฌธ์ด๋ค.
3๏ธโฃ ๋ฆฌํฌ์งํ ๋ฆฌ ์ง์ - QuerydslRepositorySupport
QuerydslRepositorySupport
MemberRepositoryImpl
MemberRepositoryImpl์ QuerydslRepositorySupport๋ฅผ ์์๋ฐ์์ ์ฌ์ฉํด์ฃผ๋ฉด ๋๋๋ฐ, ์ด๋ ์์ฑ์๋ ์ด๋ฐ์์ผ๋ก ๋ฐ์์์ผ ํ๋ค.
QuerydslRepositorySupport๋ Querydls3์ ์ง์?ํ๊ธฐ ๋๋ฌธ์ select๊ฐ ๋จผ์ ๊ฐ ์๋๋ผ select๊ฐ ๊ฐ์ฅ ๋ค์ ๋์จ๋ค.
from์ด ๊ฐ์ฅ ๋จผ์ ๋์ค๋ ํ์
QuerydslRepositorySupport๋ฅผ ์ฌ์ฉํด์ ํ์ด์ง์ ํ ๋๋
getQuerydsl().applyPagination()์ ํ์ด์ง๊ณผ ์ฟผ๋ฆฌ๋ฅผ ํ๋ผ๋ฏธํฐ๋ก ์ฃผ๋ฉด ๋๋ค.
๊ทธ๋ฆฌ๊ณ ๊ฒฐ๊ณผ์ ๋ํด์ ๋ค์ getReulstsํ๋ฉด ๋๋ค.
applyPagination()์ offset, limit์ด ์๊ธฐ ๋๋ฌธ์ ์ด ๊ฐ๋ค์ ์๋ตํด์ค๋ ๋๋ค.
์ฅ์
- getQuerydsl().applyPagination() : ์คํ๋ง ๋ฐ์ดํฐ๊ฐ ์ ๊ณตํ๋ ํ์ด์ง์ Querydsl๋ก ํธ๋ฆฌํ๊ฒ ๋ณํ ๊ฐ๋ฅํ๋ค.
(๊ทผ๋ฐ Sort๋ ์ค๋ฅ ๋ฐ์ํ๋ค..)
- from()์ผ๋ก ์์ ๊ฐ๋ฅ -> ์ด๊ฒ๋ ์ต๊ทผ์๋ QueryFactory๋ฅผ ์ฌ์ฉํด์ select()๋ก ์์ํ๋ ๊ฒ์ด ๋ ๋ช ์์ ์ด๋ค.
- EntityManager ์ ๊ณต
๋จ์
- Querydsl 3.x ๋ฒ์ ์ ๋์์ผ๋ก ๋ง๋ฆ
- Qeurydsl 4.x์ ๋์จ JpaQueryFactory๋ก ์์ํ ์ ์์.
- QueryFactory๋ฅผ ์ ๊ณตํ์ง ์์
- ์คํ๋ง ๋ฐ์ดํฐ Sort ๊ธฐ๋ฅ์ด ์ ์ ๋์ํ ์ง์์,,
4๏ธโฃ Querydsl ์ง์ ํด๋์ค ์ง์ ๋ง๋ค๊ธฐ
: ์คํ๋ง ๋ฐ์ดํฐ๊ฐ ์ ๊ณตํ๋ QuerydslRepositorySupport๊ฐ ์ง๋ ํ๊ณ๊ฐ ์๊ธฐ ๋๋ฌธ์ ์ด๋ฅผ ๊ทน๋ณตํ๊ธฐ ์ํด ์ง์ Querydls ์ง์ ํด๋์ค๋ฅผ ๋ง๋ ๋ค!
์ฅ์
- ์คํ๋ง ๋ฐ์ดํฐ๊ฐ ์ ๊ณตํ๋ ํ์ด์ง์ ํธ๋ฆฌํ๊ฒ ๋ณํ
- ํ์ด์ง๊ณผ ์นด์ดํธ ์ฟผ๋ฆฌ ๋ถ๋ฆฌ ๊ฐ๋ฅ
- ์คํ๋ง ๋ฐ์ดํฐ Sort ์ง์
- select(), selectFrom() ์ผ๋ก ์์ ๊ฐ๋ฅ
- EntityManager(), QueryFactory ์ ๊ณต
Querydsl4RepositorySupport
package study.querydesl.repository.support;
import com.querydsl.core.types.EntityPath;
import com.querydsl.core.types.Expression;
import com.querydsl.core.types.dsl.PathBuilder;
import com.querydsl.jpa.impl.JPAQuery;
import com.querydsl.jpa.impl.JPAQueryFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.support.JpaEntityInformation;
import
org.springframework.data.jpa.repository.support.JpaEntityInformationSupport;
import org.springframework.data.jpa.repository.support.Querydsl;
import org.springframework.data.querydsl.SimpleEntityPathResolver;
import org.springframework.data.repository.support.PageableExecutionUtils;
import org.springframework.stereotype.Repository;
import org.springframework.util.Assert;
import javax.annotation.PostConstruct;
import javax.persistence.EntityManager;
import java.util.List;
import java.util.function.Function;
/**
* Querydsl 4.x ๋ฒ์ ์ ๋ง์ถ Querydsl ์ง์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ
*
* @author Younghan Kim
* @see org.springframework.data.jpa.repository.support.QuerydslRepositorySupport
*/
@Repository
public abstract class Querydsl4RepositorySupport {
private final Class domainClass;
private Querydsl querydsl;
private EntityManager entityManager;
private JPAQueryFactory queryFactory;
public Querydsl4RepositorySupport(Class<?> domainClass) {
Assert.notNull(domainClass, "Domain class must not be null!");
this.domainClass = domainClass;
}
@Autowired
public void setEntityManager(EntityManager entityManager) {
Assert.notNull(entityManager, "EntityManager must not be null!");
JpaEntityInformation entityInformation =
JpaEntityInformationSupport.getEntityInformation(domainClass, entityManager);
SimpleEntityPathResolver resolver = SimpleEntityPathResolver.INSTANCE;
EntityPath path = resolver.createPath(entityInformation.getJavaType());
this.entityManager = entityManager;
this.querydsl = new Querydsl(entityManager, new
PathBuilder<>(path.getType(), path.getMetadata()));
this.queryFactory = new JPAQueryFactory(entityManager);
}
@PostConstruct
public void validate() {
Assert.notNull(entityManager, "EntityManager must not be null!");
Assert.notNull(querydsl, "Querydsl must not be null!");
Assert.notNull(queryFactory, "QueryFactory must not be null!");
}
protected JPAQueryFactory getQueryFactory() {
return queryFactory;
}
protected Querydsl getQuerydsl() {
return querydsl;
}
protected EntityManager getEntityManager() {
return entityManager;
}
protected <T> JPAQuery<T> select(Expression<T> expr) {
return getQueryFactory().select(expr);
}
protected <T> JPAQuery<T> selectFrom(EntityPath<T> from) {
return getQueryFactory().selectFrom(from);
}
protected <T> Page<T> applyPagination(Pageable pageable,
Function<JPAQueryFactory, JPAQuery> contentQuery) {
JPAQuery jpaQuery = contentQuery.apply(getQueryFactory());
List<T> content = getQuerydsl().applyPagination(pageable,
jpaQuery).fetch();
return PageableExecutionUtils.getPage(content, pageable,
jpaQuery::fetchCount);
}
protected <T> Page<T> applyPagination(Pageable pageable,
Function<JPAQueryFactory, JPAQuery> contentQuery, Function<JPAQueryFactory,
JPAQuery> countQuery) {
JPAQuery jpaContentQuery = contentQuery.apply(getQueryFactory());
List<T> content = getQuerydsl().applyPagination(pageable,
jpaContentQuery).fetch();
JPAQuery countResult = countQuery.apply(getQueryFactory());
return PageableExecutionUtils.getPage(content, pageable,
countResult::fetchCount);
}
}
QuerydslRepositorySupprot๊ฐ QueryFactory๋ฅผ ์ฌ์ฉํ์ง ์๊ธฐ ๋๋ฌธ์ ์ด๋ฅผ ๋ง์ถ๊ธฐ ์ํด์ ๊ฐ์ฌ๋์ด ์ง์ ๋ง๋ ๊ฒ์ผ๋ก
์ด๊ฑด ์๋ฐ 8 ๊ธฐ๋ฅ์ด ์ฌ์ฉ๋๊ธฐ ๋๋ฌธ์ ์ด๋ฐ ์ฌํญ์ ์ข ์๊ณ ์์ด์ผ ์ดํด ๊ฐ๋ฅํ ์ฝ๋๋ค.
Querydsl4RepositorySupport ์ฌ์ฉ ์ฝ๋
MemberTestRepository
Querydsl4RepositorySupport๋ฅผ ์์๋ฐ๊ณ , basicSelect()๋ฅผ ๋ณด๋ฉด queryFactory ์์ด select๋ก ์์ํ๋ ๊ฒ์ ์ ์ ์๋ค.
(Querydsl4RepositorySupport์ ๊ตฌํ๋์ด ์๊ธฐ ๋๋ฌธ)
applyPagination()์ ์์ searchPageByApplyPage()๋ฅผ ์ถ์ํํ Querydsl4RepositorySupport๋ฅผ ์ฌ์ฉํด ์ข ๋ ๊ฐ๋จํ๊ฒ ์์ฑํ ์ฝ๋์ด๋ค.
๋ณด๋ฉด List<T> content ๋ถ๋ถ๊ณผ PageableExecutionUtils๋ฅผ ์ฌ์ฉํ๋๊ฑฐ ๋ณด๋ฉด ์์ ์ฝ๋์ ๋์ผํ ์ฝ๋๋ฅผ Querydsl4RepositorySupport๋ก ๋นผ๋ ๊ฒ์ด๋ค.
๊ทธ๋ฆฌ๊ณ ์ด์ ์ ํ์ด์ง ๊ด๋ จ ์ฝ๋๋ฅผ ์งค ๋ ์นด์ดํธ ์ฟผ๋ฆฌ๋ฅผ ๋ฐ๋ก ๋บ Complex ๋ฒ์ ์ ๋ง๋ค์์๋๋ฐ,
contentQuery ๋ค์์ countQuery๋ฅผ ์ถ๊ฐํด์ฃผ๋ฉด ๋๋ค.
'์ธํ๋ฐ > ์ค์ ! QueryDSL' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[QueryDSL] fetchResults(), fetchCount() Deprecated (0) | 2022.10.18 |
---|---|
[QueryDSL] 6. ์ค๋ฌด ํ์ฉ - ์คํ๋ง ๋ฐ์ดํฐ JPA์ QueryDSL (0) | 2022.10.17 |
[QueryDSL] 5. ์ค๋ฌด ํ์ฉ - ์์ JPA์ QueryDSL (0) | 2022.10.12 |
[QueryDSL] 4. ์ค๊ธ ๋ฌธ๋ฒ (0) | 2022.10.11 |
[QueryDSL] 3. ๊ธฐ๋ณธ ๋ฌธ๋ฒ(2) (์๋ธ์ฟผ๋ฆฌ, ์์, ๋ฌธ์ ๋ํ๊ธฐ) (0) | 2022.10.11 |