QueryDSL

QueryDSL์€ ์˜คํ”ˆ์†Œ์Šค ํ”„๋กœ์ ํŠธ์ด๊ณ  ๋‹ค์ˆ˜์˜ ํ”„๋กœ์ ํŠธ์—์„œ ์ง€์›๋˜๊ณ  ์žˆ๋Š” ์ƒํ™ฉ์ด๋‹ค ์ด๊ฒŒ ๋ญ”๊ฐ€ -> jpql์„ ์‚ฌ์šฉํ•ด์„œ ์ฟผ๋ฆฌ ์ฆ‰ ๋ฐ์ดํ„ฐ๋ฅผ ์กฐํšŒํ•˜๋Š”๋ฐ ๊ธฐ๋Šฅ์ด ํŠนํ™”๋˜์–ด ์žˆ๋Š” ํ”„๋กœ์ ํŠธ

์‚ฌ์šฉ ๋ฐฉ๋ฒ•

๊ธฐ๋ณธ์ ์œผ๋กœ ์ œ๊ณตํ•ด์ฃผ๋Š” ๊ธฐ๋Šฅ์€ ์•„๋‹ˆ๊ธฐ ๋•Œ๋ฌธ์— ๋”ฐ๋กœ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์ฃผ์ž…๋ฐ›์•„์•ผ ํ•จ querydsl-jpa : QueryDSL JPA ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ querydsl-apt : ์ฟผ๋ฆฌ ํƒ€์ž…์„ ์ƒ์„ฑํ•  ๋•Œ ํ•„์š”ํ•œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์—ฌ๊ธฐ์„œ ๋‚˜์˜จ 2๊ฐ€์ง€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋Š” ํ•„์ˆ˜..! ํ•„์š”ํ•  ๋•Œ ๊ตฌ๊ธ€๋งํ•ด์„œ ์„ค์น˜ํ•ด ์‚ฌ์šฉํ•˜์ž

QueryDSL์„ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ์šฐ์„ ์ ์œผ๋กœ JPAQuery ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ค์–ด์•ผ ํ•œ๋‹ค ์ด๋•Œ ์—”ํ‹ฐํ‹ฐ ๋งค๋‹ˆ์ €๋ฅผ ์ƒ์„ฑ์ž์—๊ฒŒ ๋„˜๊ฒจ์ค€ ๋’ค, ๋‹ค์Œ์œผ๋กœ ์‚ฌ์šฉํ•  ์ฟผ๋ฆฌ ํƒ€์ž…์„ ์ƒ์„ฑํ•˜๋Š”๋ฐ ์ƒ์„ฑ์ž์—๋Š” ๋ณ„์นญ์„ ์ฃผ๋ฉด ๋˜๊ณ , ์ด ๋ณ„์นญ์€ jpql์—์„œ ์‚ฌ์šฉํ•˜๋˜ ๋ฐฉ์‹๊ณผ ๋™์ผํ•˜๊ฒŒ ์ง„ํ–‰ํ•˜๋ฉด ๋œ๋‹ค

์ฝ”๋“œ๋กœ ํ•œ๋ฒˆ ๋ด๋ณด์ž

public void queryDSL(){
    EntityManager em = emf.createEntityManager();
    
    JPAQuery query = new JPAQuery(em);
    QMember qMember = new QMember("m");
    List<Member> members = query
                             .from(qMember)
                             .where(qMember.name.eq("ํšŒ์›1"))
                             .orderBy(qMember.name.desc())
                             .list(qMember);
}

๊ฐ์ฒด๋ฅผ ๋งŒ๋“ค๊ณ ๋ญ ์„ธํŒ…์„ ์ œ์™ธํ•˜๊ณ  ์‹ค์ œ๋กœ ์ฟผ๋ฆฌ๋ฅผ ๋งŒ๋“œ๋Š” ๋ถ€๋ถ„์„ ๋ณด๋ฉด ๊ทธ๋ ‡๊ฒŒ ์–ด๋ ต์ง€ ์•Š๊ฒŒ sql๋ฌธ๊ณผ ๋‹ฎ์•„์žˆ๋‹ค..!

์ฟผ๋ฆฌ ํƒ€์ž…(Q) ์—ฌ๊ธฐ์„œ๋Š” QMember๋กœ ๋งŒ๋“ค์—ˆ๋Š”๋ฐ ์š”๋†ˆ์€ ์‚ฌ์šฉํ•˜๊ธฐ ํŽธ๋ฆฌํ•˜๋„๋ก ๊ธฐ๋ณธ ์ธ์Šคํ„ด์Šค๋ฅผ ๋ณด๊ด€ํ•˜๋Š”๊ฒŒ ์ข‹๊ธด ํ•˜๋‹ค ํ•˜์ง€๋งŒ ๊ฐ™์€ ์—”ํ‹ฐํ‹ฐ๋ฅผ ์กฐ์ธํ•˜๊ฑฐ๋‚˜ ๊ฐ™์€ ์—”ํ‹ฐํ‹ฐ๋ฅผ ์„œ๋ธŒ์ฟผ๋ฆฌ์— ์‚ฌ์šฉํ•˜๋ฉด ๊ฐ™์€ ๋ณ„์นญ์ด ์‚ฌ์šฉ๋˜๊ธฐ ๋•Œ๋ฌธ์— ์ด๋Ÿด๋•Œ๋Š” ๋ณ„์นญ์„ ์ง์ ‘ ์ง€์ •

๊ฒ€์ƒ‰ ์กฐ๊ฑด ์ฟผ๋ฆฌ

where์ ˆ์—์„œ ์กฐ๊ฑด๋ฌธ์„ ์ž‘์„ฑํ•ด์ฃผ๋Š”๋ฐ ์ด ๋‚ด๋ถ€์—์„œ๋„ and ๋‚˜ or์™€ ๊ฐ™์ด ์ •๋ง ์ฟผ๋ฆฌ๋ฌธ์„ ์ž‘์„ฑํ•˜๋“ฏ ์ž‘์„ฑํ•˜๋Š” ๊ฒƒ์ด ๊ฐ€๋Šฅํ•˜๋‹ค

JPAQuery query = new JPAQuery(em);
QItem item = QItem.item;
List<Item> list = query.from(item)
                    .where(item.name.eq("์ข‹์€ ์ƒํ’ˆ").and(item.price.gt(20000)))
                    .list(item);

์ด๋ ‡๊ฒŒ .and, .or๋ฅผ ์‚ฌ์šฉํ•ด์„œ ์กฐ๊ฑด์„ ๋„ฃ์„ ์ˆ˜ ์žˆ์œผ๋ฉฐ ์ถ”๊ฐ€์ ์œผ๋กœ where(item.name.eq("์ข‹์€์ƒํ’ˆ"), item.price.gt(20000)) ์ด๋ ‡๊ฒŒ ์ถ”๊ฐ€ ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ์‚ฌ์šฉํ•ด์„œํ•˜๋ฉด and๊ฐ€ ๋จ -> ์ด์™ธ์—๋„ between, contains, startsWith๋“ฑ๋“ฑ ์ด๋ ‡๊ฒŒ ๋‹ค์–‘ํ•˜๊ฒŒ ์žˆ์œผ๋‹ˆ๊นŒ intellij, ๊ตฌ๊ธ€์˜ ๋„์›€์„ ๋ฐ›์œผ๋ฉฐ ์‚ฌ์šฉ

๊ฒฐ๊ณผ ์กฐํšŒ

์ฟผ๋ฆฌ์˜ ์ž‘์„ฑ์ด ๋๋‚˜๊ณ  ๊ฒฐ๊ณผ๋ฅผ ์กฐํšŒํ•˜๋Š”๋ฐ ์žˆ์–ด์„œ ๋งˆ์ง€๋ง‰์—๋Š” ๊ฒฐ๊ณผ๋ฅผ ๋ฐ›์„ ๋ฉ”์†Œ๋“œ๋ฅผ ๋„ฃ์–ด์ค˜์•ผ ํ•œ๋‹ค ๋Œ€ํ‘œ์ ์ธ ๋ฉ”์†Œ๋“œ๋“ค

  • uniqueResult() : ์กฐํšŒ ๊ฒฐ๊ณผ๊ฐ€ ํ•˜๋‚˜์ผ ๋•Œ ์‚ฌ์šฉํ•˜๊ณ , ๋งŒ์•ฝ ์—†์œผ๋ฉด null, ๋งŒ์•ฝ ๊ฒฐ๊ณผ๊ฐ€ ์—ฌ๋Ÿฌ๊ฐœ์ด๋ฉด Exception

  • singleResult() : uniqueResult()์™€ ๋™์ผํ•˜์ง€๋งŒ ๋งŒ์•ฝ ๊ฒฐ๊ณผ๊ฐ€ ์—ฌ๋Ÿฌ๊ฐœ์ด๋ฉด ๋งจ ์•ž์—๊ฒƒ ๋ฆฌํ„ด

  • list() : ๊ฒฐ๊ณผ๊ฐ€ ํ•˜๋‚˜ ์ด์ƒ์ผ ๋•Œ ์‚ฌ์šฉ

ํŽ˜์ด์ง•, ์ •๋ ฌ

์šฐ์„  ์ •๋ ฌ๊ฐ™์€ ๊ฒฝ์šฐ๋Š” orderBy๋ฉ”์†Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋Š”๋ฐ ์ •๋ ฌ ๋ฐฉ์‹์„ ์ง€์ •ํ•˜๋Š”๋ฐ๋Š” asc(), desc()์„ ์ถ”๊ฐ€๋กœ ์‚ฌ์šฉ ํŽ˜์ด์ง•๊ฐ™์€ ๊ฒฝ์šฐ์—๋Š” offset๋ฉ”์†Œ๋“œ์™€ limit๋ฉ”์†Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•ด๋„ ๊ดœ์ฐฎ๊ณ  restrict() ๋ฉ”์†Œ๋“œ์— ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๋„ฃ์–ด์ค˜๋„ ๊ฐ€๋Šฅํ•˜๋‹ค- limit, offset ์ˆœ์„œ ์‚ฌ์šฉ ์˜ˆ์‹œ๋ฅผ ๋ณด์ž

QueryModifiers queryModifiers = new QueryModifiers(20L, 10L); 
List<Item> list = query.from(item)
                     .restrict(queryModifiers)
                     .list(item);

์ด์™ธ์—๋„ ์ •๋ ฌlist๋ฅผ ๋ฝ‘์•˜์„ ๋•Œ getTotal, getLimit, getOffset, getResults์™€ ๊ฐ™์€ ๋ฉ”์†Œ๋“œ๋ฅผ ํ†ตํ•ด์„œ ๊ฒฐ๊ณผ๋“ค์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค!

๊ทธ๋ฃน

์šฐ๋ฆฌ๊ฐ€ ์•Œ๊ณ  ์žˆ๋Š” groupBy, having์„ ํ†ตํ•ด์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค

์กฐ์ธ

์กฐ์ธ์€ innerJoin, leftJoin, rightJoin, fullJoin ์ด๋ ‡๊ฒŒ ์กด์žฌํ•˜๊ณ  ์žˆ์œผ๋ฉฐ fetchJoin๋„ ์‚ฌ์šฉ ๊ฐ€๋Šฅ ์กฐ์ธ์˜ ๊ธฐ๋ณธ ๋ฌธ๋ฒ•์€ ์ฒซ ๋ฒˆ์งธ ํŒŒ๋ผ๋ฏธํ„ฐ์—์„œ ์กฐ์ธ ๋Œ€์ƒ์„ ์ง€์ •ํ•˜๊ณ  ๋‘ ๋ฒˆ์งธ ํŒŒ๋ผ๋ฏธํ„ฐ์—์„œ ๋ณ„์นญ์œผ๋กœ ์‚ฌ์šฉํ•  ์ฟผ๋ฆฌ ํƒ€์ž…์„ ์ง€์ • ์กฐ์ธ์˜ ์˜ˆ์‹œ๋ฅผ ๋ณด์ž

QOrder order = QOrder.order;
QMember member = QMember.member;
QOrderItem orderItem = QOrderItem.orderItem;

//๊ธฐ๋ณธ์ ์ธ ์กฐ์ธ
query.from(order)
    .join(order.member, member)
    .leftJoin(order.orderItem, orderItem)
    .list(order);

//on์„ ์‚ฌ์šฉํ•œ ์กฐ์ธ
query.from(order)
    .leftJoin(order.orderItem, orderItem)
    .on(orderItem.count.gt(2))
    .list(order);
    
//ํŒจ์น˜ ์กฐ์ธ์„ ์‚ฌ์šฉ
query.from(order)
    .innerJoin(order.member, member).fetch()
    .leftJoin(order.orderItems, orerItem).fetch()
    .list(order);
    
//from ์ ˆ์—์„œ ์—ฌ๋Ÿฌ ์กฐ๊ฑด ์‚ฌ์šฉ
query.from(order, member)
    .where(order.member.eq(member))
    .list(order);    

์„œ๋ธŒ ์ฟผ๋ฆฌ

์„œ๋ธŒ ์ฟผ๋ฆฌ๋Š” ์‚ฌ์šฉํ•˜๋Š”๋ฐ ์žˆ์–ด์„œ JPASubQuery๋ฅผ ์ƒ์„ฑํ•ด์„œ ์‚ฌ์šฉํ•˜๊ณ , ๊ฒฐ๊ณผ๋ฅผ ๋ฐ›๋Š”๋ฐ ์žˆ์–ด์„œ๋Š” ๊ธฐ์กด๊ณผ ๋น„์Šทํ•˜๊ฒŒ unique(), list()๋ฅผ ์‚ฌ์šฉ ์„œ๋ธŒ ์ฟผ๋ฆฌ, ๋‹ค์ˆ˜์˜ ์„œ๋ธŒ ์ฟผ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์˜ˆ์‹œ๋ฅผ ๋ณด์ž

QItem item = QItem.item;
QItem itemSub = new QItem("itemSub");

//๋‹จ์ผ ์„œ๋ธŒ ์ฟผ๋ฆฌ
query.from(item)
    .where(
        item.price.eq(
            new JPASubQuery().from(itemSub)
                .unique(itemSub.price.max())
        )
    )
    .list(item);
    
//์—ฌ๋Ÿฌ ๊ฐœ์˜ ์„œ๋ธŒ ์ฟผ๋ฆฌ
query.from(item)
    .where(
        item.in(
            new JPASubQuery().from(itemSub)
                .where(item.name.eq(itemSub.name))
                .list(itemSub)
        )
    )
    .list()

ํ”„๋กœ์ ์…˜๊ณผ ๊ฒฐ๊ณผ ๋ฐ˜ํ™˜

select ์ ˆ์— ์กฐํšŒ ๋Œ€์ƒ์„ ์ง€์ •ํ•˜๋Š” ๊ฒƒ์„ ๋ณด๊ณ  ํ”„๋กœ์ ์…˜์ด๋ผ๊ณ  ๋ถ€๋ฆ„ ๋งŒ์•ฝ ๊ฒฐ๊ณผ๋ฅผ ๋‹ค์ˆ˜์˜ ์ปฌ๋Ÿผ์œผ๋กœ ๋ฐ›๊ณ  ์‹ถ๋‹ค๋ฉด Tuple์„ ์‚ฌ์šฉํ•ด์„œ ์ง„ํ–‰ํ•  ์ˆ˜ ์žˆ๋‹ค ๋งŒ์•ฝ ๊ฒฐ๊ณผ๋ฅผ ์—”ํ‹ฐํ‹ฐ๊ฐ€ ์•„๋‹Œ ๋‹ค๋ฅธ ํŠน์ • ๊ฐ์ฒด๋กœ ๋ฐ›๊ณ  ์‹ถ๋‹ค๋ฉด ๋นˆ ์ƒ์„ฑ์„ ํ†ตํ•ด์„œ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ›์„ ์ˆ˜ ์žˆ๋Š”๋ฐ ์ด๋Ÿฌํ•œ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๋ฐฉ๋ฒ•์€ ํ”„๋กœํผํ‹ฐ ์ ‘๊ทผ, ํ•„๋“œ ์ง์ ‘ ์ ‘๊ทผ, ์ƒ์„ฑ์ž ์‚ฌ์šฉ ์ด๋ ‡๊ฒŒ ๋‚˜๋ˆ„์–ด์ ธ ์žˆ๋‹ค ์ถ”๊ฐ€๋กœ ๋งŒ์•ฝ distinct๋ฅผ ๋ถ™ํžˆ๊ณ  ์‹ถ๋‹ค๋ฉด query.distinct().from(ํ…Œ์ด๋ธ”)... ์ด๋ ‡๊ฒŒ ์‚ฌ์šฉ

์ˆ˜์ •, ์‚ญ์ œ ๋ฐฐ์น˜ ์ฟผ๋ฆฌ

jpql ๋ฐฐ์น˜ ์ฟผ๋ฆฌ์™€ ๊ฐ™์ด ์˜์†์„ฑ ์ปจํ…์ŠคํŠธ๋ฅผ ๋ฌด์‹œํ•˜๊ณ  ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์ง์ ‘์ ์œผ๋กœ ์ฟผ๋ฆฌํ•œ๋‹ค๋Š” ์ ..! ๋‚˜์ค‘์— jpql ๋ฐฐ์น˜ ์ฟผ๋ฆฌ๋ฅผ ๋‹ค๋ฃฌ๋‹ค..!

๋™์  ์ฟผ๋ฆฌ

๋™์  ์ฟผ๋ฆฌ๋Š” BooleanBuilder๋ฅผ ์‚ฌ์šฉํ•ด์„œ ํŠน์ • ์กฐ๊ฑด์— ๋”ฐ๋ฅธ ๋™์  ์ฟผ๋ฆฌ๋ฅผ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค

๋ฉ”์†Œ๋“œ ์œ„์ž„

๋ฉ”์†Œ๋“œ ์œ„์ž„์„ ์‚ฌ์šฉํ•˜๊ฒŒ๋˜๋ฉด ์ฟผ๋ฆฌ ํƒ€์ž…์— ๊ฒ€์ƒ‰ ์กฐ๊ฑด์„ ์ง์ ‘ ์ •์˜ํ•˜๋Š” ๊ฒƒ์ด ๊ฐ€๋Šฅํ•˜๋‹ค ๊ฒ€์ƒ‰ ์กฐ๊ฑด์€ ์ด๋ ‡๊ฒŒ ์ •์˜ํ•œ๋‹ค

public class ItemExpression{
    @QueryDelegate(Item.class)
    public static BooleanExpression isExpensive(QItem item, Integer price){
        return item.price.gt(price);
    }
}

์ด๋ ‡๊ฒŒ ์ผ๋‹จ ์ •์ ๋ฉ”์†Œ๋“œ๋ฅผ ๋งŒ๋“ค๊ณ , QueryDelegate์œผ๋กœ ์ด ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•  ์—”ํ‹ฐํ‹ฐ๋ฅผ ์ง€์ •ํ•˜๊ณ  ๊ฑฐ๊ธฐ์— ์• ๋…ธํ…Œ์ด์…˜์œผ๋กœ ์ •ํ•ด์ค€๋‹ค ์ •์  ๋ฉ”์†Œ๋“œ์˜ ์ฒซ ๋ฒˆ์งธ ํŒŒ๋ผ๋ฏธํ„ฐ๋Š” ๋Œ€์ƒ ์—”ํ‹ฐํ‹ฐ์˜ ์ฟผ๋ฆฌ ํƒ€์ž…์„ ์ง€์ •ํ•˜๊ณ  ๋‚˜๋จธ์ง€๋Š” ํ•„์š”ํ•œ ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ์ง€์ •

QueryDSL ์ •๋ฆฌ

๋ฌธ์ž๊ฐ€ ์•„๋‹Œ ์ฝ”๋“œ๋กœ ์ฟผ๋ฆฌ๋ฅผ ์ž‘์„ฑํ•  ๋•Œ, ๋ณต์žกํ•œ ๋™์  ์ฟผ๋ฆฌ๋ฅผ ์–ด๋–ป๊ฒŒ ํ•ด๊ฒฐํ•˜๋ƒ์—์„œ ์ •๋ง ์ข‹์€ ๋‹ต์•ˆ์„ ์ฃผ๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ด๋‹ค!! ๊ทธ๋ฆฌ๊ณ  ๊ฒฐ๊ตญ์€ ์ปดํŒŒ์ผ๋Ÿฌ์˜ ํ™•์ธ์„ ๋ฐ›๊ณ  ์ฟผ๋ฆฌ๋ฅผ ์‹คํ–‰ํ•˜๊ธฐ๋„ ํ•˜๋ฉด์„œ ์ฟผ๋ฆฌ๋ฅผ ์ž‘์„ฑํ•˜๋Š”๋ฐ ์žˆ์–ด์„œ ide์˜ ๋„์›€๋„ ๋ฐ›๊ธฐ ๋•Œ๋ฌธ์— ์•ˆ์ „ํ•˜๊ฒŒ ์ฟผ๋ฆฌ๋ฅผ ์ž‘์„ฑํ•˜๋Š” ๊ฒƒ์ด ๊ฐ€๋Šฅํ•˜๊ธฐ์— ์œ ์šฉํ•˜๋‹ค๋Š” ์ƒ๊ฐ์ด ๋“ ๋‹ค

<br

Last updated

Was this helpful?