JPQL

JPQL : Java Persistence Query Language

  • ๊ฐ์ฒด์ง€ํ–ฅ ์ฟผ๋ฆฌ ์–ธ์–ด๋กœ, ํ…Œ์ด๋ธ”์„ ๋Œ€์ƒ์œผ๋กœ ์ฟผ๋ฆฌํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ ์—”ํ‹ฐํ‹ฐ ๊ฐ์ฒด๋ฅผ ๋Œ€์ƒ์œผ๋กœ ์ฟผ๋ฆฌํ•œ๋‹ค.

  • SQL์„ ์ถ”์ƒํ™”ํ•ด์„œ ํŠน์ • ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค SQL์— ์˜์กดํ•˜์ง€ ์•Š๋Š”๋‹ค.

  • JPQL์€ ๊ฒฐ๊ตญ SQL๋กœ ๋ณ€ํ™˜๋œ๋‹ค.

๊ธฐ๋ณธ ๋ชจ๋ธ๋ง img.png

ํ”„๋กœ์ ์…˜

SELECT์ ˆ์— ์กฐํšŒํ•  ๋Œ€์ƒ์„ ์ง€์ •ํ•  ์ˆ˜ ์žˆ๋‹ค. ํ”„๋กœ์ ์…˜ ๋Œ€์ƒ์œผ๋กœ ์—”ํ‹ฐํ‹ฐ, ์ž„๋ฒ ๋””๋“œ ํƒ€์ž…, ์Šค์นผ๋ผ ํƒ€์ž…(์ˆซ์ž, ๋ฌธ์ž ๋“ฑ ๊ธฐ๋ณธ ๋ฐ์ดํ„ฐ)์ด ์žˆ๋‹ค.

  • ์—”ํ‹ฐํ‹ฐ ํ”„๋กœ์ ์…˜

select m from Member m
select m.team from Member m

์ฒ˜์Œ์€ ํšŒ์›์„ ์กฐํšŒํ•˜๊ณ  ๋‘ ๋ฒˆ์งธ๋Š” ํšŒ์›๊ณผ ์—ฐ๊ด€๋œ ํŒ€์„ ์กฐํšŒํ•œ๋‹ค. ์ด๋ ‡๊ฒŒ ์กฐํšŒํ•œ ์—”ํ‹ฐํ‹ฐ๋Š” ์˜์†์„ฑ ์ปจํ…์ŠคํŠธ์—์„œ ๊ด€๋ฆฌ๋œ๋‹ค.

๋‘ ๋ฒˆ์งธ๋Š” ๋‹ค์Œ์ฒ˜๋Ÿผ ๋ณ€๊ฒฝํ•  ์ˆ˜๋„ ์žˆ๋‹ค.

select t from Member m join m.team t

์‹คํ–‰๋˜๋Š” ์ฟผ๋ฆฌ๋Š” ๋˜‘๊ฐ™๋‹ค. ์ฐจ์ด์ ์ด๋ผ๊ณ  ํ•œ๋‹ค๋ฉด ๊ฐœ๋ฐœ์ž๊ฐ€ ์ด ์ฟผ๋ฆฌ๋Š” ์กฐ์ธ์„ ํ†ตํ•ด ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ค๋Š”๊ตฌ๋‚˜๋ผ๊ณ  ์ธ์ง€ํ•˜๋Š” ๊ฒƒ ์ •๋„๋‹ค.

  • ์ž„๋ฒ ๋””๋“œ ํƒ€์ž… ํ”„๋กœ์ ์…˜

select o.address from Order o

์ž„๋ฒ ๋””๋“œ ํƒ€์ž…์€ ๊ฐ’ ํƒ€์ž…์ด๊ธฐ ๋•Œ๋ฌธ์— ์กฐํšŒ์˜ ์‹œ์ž‘์ ์ด ๋  ์ˆ˜ ์—†๋‹ค.

//์ž˜๋ชป๋œ ์ฟผ๋ฆฌ
select a from Address a
  • ์Šค์นผ๋ผ ํƒ€์ž… ํ”„๋กœ์ ์…˜

select m.name, m.age from Member m

์ด๋ ‡๊ฒŒ ๋‘ ๊ฐœ์˜ ํƒ€์ž…์ด ๋‹ค๋ฅธ ํ•„๋“œ๋ฅผ ํ”„๋กœ์ ์…˜ํ•ด์„œ ํƒ€์ž…์„ ์ง€์ •ํ•  ์ˆ˜ ์—†์œผ๋ฏ€๋กœ TypeQuery๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๋‹ค.

NEW๋ช…๋ น์–ด๋ฅผ ํ†ตํ•˜์—ฌ ๋ฐ”๋กœ DTO๋กœ ๋ณ€ํ™˜ํ•  ์ˆ˜ ์žˆ๋‹ค.

@AllArgsConstructor
@Getter
public class MemberDto {
    private String name;
    private int age;
}

em.createQuery("select new hellojpa.MemberDto(m.name, m.age) from Member m", MemberDto.class).getResultList();
  • ํŒจํ‚ค์ง€ ๋ช…์„ ํฌํ•จํ•œ ์ „์ฒด ํด๋ž˜์Šค๋ช…์„ ์ž…๋ ฅํ•ด์•ผ ํ•œ๋‹ค.

  • ์ˆœ์„œ์™€ ํƒ€์ž…์ด ์ผ์ฐจํ•˜๋Š” ์ƒ์„ฑ์ž๊ฐ€ ํ•„์š”ํ•˜๋‹ค.

ํŽ˜์ด์ง•

JPA๋Š” ํŽ˜์ด์ง•์„ ๋‹ค์Œ API๋กœ ์ถ”์ƒํ™”ํ–ˆ๋‹ค.

  • setFirstResult(int startPosition) : ์กฐํšŒ ์‹œ์ž‘ ์œ„์น˜(0๋ถ€ํ„ฐ ์‹œ์ž‘)

  • setMaxResult(int maxResult) : ์กฐํšŒํ•  ๋ฐ์ดํ„ฐ ์ˆ˜

em.createQuery("select m from Member m order by m.age desc", Member.class)
  .setFirstResult(0)
  .setMaxResults(10)
  .getResultList();

์กฐ์ธ

  • ๋‚ด๋ถ€ ์กฐ์ธ

em.createQuery("select m from Member m inner join m.team t where t.name = :teamName", Member.class)
  .setParameter("teamName", teamName)
  .getResultList();

ํšŒ์›๊ณผ ํŒ€์„ ๋‚ด๋ถ€ ์กฐ์ธํ•ด์„œ teamName์— ์†Œ์†๋œ ํšŒ์›์„ ์ฐพ๋Š”๋‹ค. inner๋Š” ์ƒ๋žต ๊ฐ€๋Šฅํ•˜๋‹ค.

  • ์™ธ๋ถ€ ์กฐ์ธ

em.createQuery("select m from Member m left outer join m.team t", Member.class)
  .getResultList();

outer๋Š” ์ƒ๋žต ๊ฐ€๋Šฅํ•˜๋‹ค.

  • ์„ธํƒ€ ์กฐ์ธ

em.createQuery("select m from Member m, Team t where m.name = t.name", Member.class)
  .getResultList();
  • ON ์ ˆ

em.createQuery("select m from Member m left join m.team t on t.name = 'teamA'", Member.class)
  .getResultList();

ํšŒ์›๊ณผ ํŒ€์„ ์กฐ์ธํ•  ๋•Œ ํŒ€์˜ ์ด๋ฆ„์ด "teamA"๋กœ ์กฐ์ธ ๋Œ€์ƒ์„ ํ•„ํ„ฐ๋งํ•  ์ˆ˜ ์žˆ๋‹ค.

em.createQuery("select m,t from Member m left join Team t on m.name = t.name")
  .getResultList();

ํšŒ์›์˜ ์ด๋ฆ„๊ณผ ํŒ€์˜ ์ด๋ฆ„์ด ๊ฐ™์€ ๋Œ€์ƒ์„ ์™ธ๋ถ€ ์กฐ์ธํ•œ๋‹ค.

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

  • ๋‚˜์ด๊ฐ€ ํ‰๊ท ๋ณด๋‹ค ๋งŽ์€ ํšŒ์›์„ ์ฐพ๋Š”๋‹ค.

select m from Member m
where m.age > (select avg(m2.age) from Member m2)
  • ํ•œ ๊ฑด์ด๋ผ๋„ ์ฃผ๋ฌธํ•œ ๊ณ ๊ฐ์„ ์ฐพ๋Š”๋‹ค.

select m from Member m
where (select count(o) from Order o where m = o.member) > 0

//์ปฌ๋ ‰์…˜ ๊ฐ’ ์—ฐ๊ด€ ํ•„๋“œ์˜ size ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•ด์„œ๋„ ๊ฐ€๋Šฅ
select m from Member m
where m.orders.size > 0

์„œ๋ธŒ ์ฟผ๋ฆฌ ์ง€์› ํ•จ์ˆ˜

  • [not] exists (subquery)

//ํŒ€A์— ์†Œ์†์ธ ํšŒ์›
select m from Member m
where exists (select t from m.team t where t.name = 'ํŒ€A')

์„œ๋ธŒ ์ฟผ๋ฆฌ์— ๊ฒฐ๊ณผ๊ฐ€ ์กด์žฌํ•˜๋ฉด ์ฐธ์ด๋‹ค. not์€ ๋ฐ˜๋Œ€

  • all, any, some (subquery)

//์ „์ฒด ์ƒํ’ˆ ๊ฐ๊ฐ์˜ ์žฌ๊ณ ๋ณด๋‹ค ์ฃผ๋ฌธ๋Ÿ‰์ด ๋งŽ์€ ์ฃผ๋ฌธ๋“ค
select o from Order o
where o.orderAmount > all(select p.stockAmount from Product p)

//์–ด๋–ค ํŒ€์ด๋“  ํŒ€์— ์†Œ์†๋œ ํšŒ์›
select m from Member m
where m.team = any(select t from Team t)

๋น„๊ต ์—ฐ์‚ฐ์ž์™€ ๊ฐ™์ด ์‚ฌ์šฉํ•˜๋ฉฐ all์€ ์กฐ๊ฑด์„ ๋ชจ๋‘ ๋งŒ์กฑํ•ด์•ผ ์ฐธ์ด๊ณ  any๋‚˜ some์€ ํ•˜๋‚˜๋ผ๋„ ๋งŒ์กฑํ•˜๋ฉด ์ฐธ์ด๋‹ค.

  • [not] in (subquery)

//20์„ธ ์ด์ƒ์„ ๋ณด์œ ํ•œ ํŒ€
select t from Team t
where t in(select t2 from Team t2 join t2.member m2 where m2.age >= 20)

์„œ๋ธŒ์ฟผ๋ฆฌ์˜ ๊ฒฐ๊ณผ ์ค‘ ํ•˜๋‚˜๋ผ๋„ ๊ฐ™์€ ๊ฒƒ์ด ์žˆ์œผ๋ฉด ์ฐธ์ด๋‹ค.

CASE ์‹

  • ๊ธฐ๋ณธ CASE ์‹

String query = "select " +
        "case when m.age<=10 then 'ํ•™์ƒ์š”๊ธˆ' " +
        "     when m.age>=60 then '๊ฒฝ๋กœ์š”๊ธˆ' " +
        "     else '์ผ๋ฐ˜ ์š”๊ธˆ' " +
        "end " +
        "from Member m";
em.createQuery(query, String.class)
  .getResultList();
  • COALESCE

select coalesce(m.name, '์ด๋ฆ„ ์—†๋Š” ํšŒ์›') from Member m

์‚ฌ์šฉ์ž ์ด๋ฆ„์ด ์—†์œผ๋ฉด '์ด๋ฆ„ ์—†๋Š” ํšŒ์›'์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

  • NULLIF

select nullif(m.name, '๊ด€๋ฆฌ์ž') from Member m

์‚ฌ์šฉ์ž ์ด๋ฆ„์ด '๊ด€๋ฆฌ์ž'๋ฉด null์„ ๋ฐ˜ํ™˜ํ•˜๊ณ  ๋‚˜๋จธ์ง€๋Š” ์ด๋ฆ„์„ ๊ทธ๋Œ€๋กœ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

Last updated