# [JPA] JPQL ๋ฌธ๋ฒ• 2 - ์ง‘ํ•ฉ ๋ฐ ์ •๋ ฌ, ์กฐ์ธ, ํŽ˜์น˜ ์กฐ์ธ
Study Repository

[JPA] JPQL ๋ฌธ๋ฒ• 2 - ์ง‘ํ•ฉ ๋ฐ ์ •๋ ฌ, ์กฐ์ธ, ํŽ˜์น˜ ์กฐ์ธ

by rlaehddnd0422

์ง‘ํ•ฉ ๋ฐ ์ •๋ ฌ

์ง‘ํ•ฉ

์ง‘ํ•ฉ์€ ์ง‘ํ•ฉํ•จ์ˆ˜(COUNT,SUM,AVG,MAX,MIN)๊ณผ ํ•จ๊ป˜ ํ†ต๊ณ„์ •๋ณด๋ฅผ ๊ตฌํ•  ๋•Œ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. 

select 
    COUNT(m),
    SUM(m.age),
    AVG(m.age),
    MAX(m.age),
    MIN(m.age)
from Member m
  • COUNT() : ๊ฒฐ๊ณผ ์ˆ˜๋ฅผ ๋ฆฌํ„ดํ•ฉ๋‹ˆ๋‹ค.
  • MAX,MIN() : ์ตœ๋Œ€ ์ตœ์†Œ ๊ฐ’์„ ๋ฆฌํ„ดํ•ฉ๋‹ˆ๋‹ค. ์ฃผ๋กœ ๋ฌธ์ž, ์ˆซ์ž, ๋‚ ์งœ์— ์‚ฌ์šฉ
  • AVG() : ํ‰๊ท ๊ฐ’์„ Double๋กœ ๋ฆฌํ„ดํ•ฉ๋‹ˆ๋‹ค. ์ˆซ์ž ํƒ€์ž…๋งŒ ์‚ฌ์šฉ ๊ฐ€๋Šฅ.
  • SUM() : ํ•ฉ์„ ๋ฆฌํ„ดํ•ฉ๋‹ˆ๋‹ค. ์ˆซ์ž ํƒ€์ž…๋งŒ ์‚ฌ์šฉ ๊ฐ€๋Šฅ
1. NULL ๊ฐ’์˜ ๊ฒฝ์šฐ์—๋Š” ๋ฌด์‹œํ•˜๋ฏ€๋กœ ํ†ต๊ณ„์— ์žกํžˆ์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
2. ๋งŒ์•ฝ ๊ฐ’์ด ์—†๋Š”๋ฐ SUM, AVG, MAX, MIN ํ•จ์ˆ˜ ์‚ฌ์šฉ ์‹œ NULL ๊ฐ’์ด ๋ฉ๋‹ˆ๋‹ค.
3. DINTINCT๋ฅผ ์ง‘ํ•ฉ ํ•จ์ˆ˜ ์•ˆ์— ์‚ฌ์šฉํ•ด์„œ ์ค‘๋ณต๋œ ๊ฐ’์„ ์ œ๊ฑฐํ•˜๊ณ  ๋‚˜์„œ ์ง‘ํ•ฉ์„ ๊ตฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
ex) SELECT COUNT(DISTINCT m.age) FROM Member m 

Group By  

Group By๋Š” ํŠน์ • ์—ด์„ ๊ธฐ์ค€์œผ๋กœ ๊ทธ๋ฃนํ™” ํ•ด์ฃผ๋Š” ๊ธฐ๋Šฅ์ž…๋‹ˆ๋‹ค.

// ํŒ€ ์ด๋ฆ„์„ ๊ธฐ์ค€์œผ๋กœ ๊ทธ๋ฃน๋ณ„๋กœ ๋ฌถ์–ด์„œ ํ†ต๊ณ„ ๋ฐ์ดํ„ฐ ๊ตฌํ•˜๊ธฐ

SELECT t.name, COUNT(m.age), SUM(m.age), AVG(m.age), MAX(m.age)
FROM Member m LEFT JOIN m.team t
GROUP BY t.name

Having ์ ˆ

Having ์ ˆ์€ GroupBy์™€ ํ•จ๊ป˜ ์‚ฌ์šฉ๋˜๋Š”๋ฐ, ๊ทธ๋ฃนํ™”ํ•œ ๋ฐ์ดํ„ฐ์— ์กฐ๊ฑด์‹์„ ๊ฑธ์–ด์„œ ์กฐํšŒํ•  ๋•Œ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

// ๊ทธ๋ฃน๋ณ„ ํ†ต๊ณ„ ๋ฐ์ดํ„ฐ์ค‘์—์„œ ํ‰๊ท  ๋‚˜์ด๊ฐ€ 10์‚ด ์ด์ƒ์ธ ๊ทธ๋ฃน๋งŒ ์กฐํšŒ
SELECT t.name, COUNT(m.age), AVG(m.age), SUM(m.age), MAX(m.age)
FROM Member m LEFT JOIN m.team t
GROUP BY t.name
HAVING AVG(m.age) >= 10

์ •๋ ฌ(Order By)

  • ORDER BY ํŠน์ •์—ด DESC : ๋‚ด๋ฆผ์ฐจ์ˆœ 
  • ORDER BY ํŠน์ •์—ด ASC : ์˜ค๋ฆ„์ฐจ์ˆœ (๊ธฐ๋ณธ ๊ฐ’)

ํŒ€ ์ด๋ฆ„์„ ๊ธฐ์ค€์œผ๋กœ ๊ทธ๋ฃนํ™” ํ•œ ํ›„ ํŒ€ ์ด๋ฆ„๊ณผ ๋ฉค๋ฒ„ ํ‰๊ท  ๋‚˜์ด๋ฅผ ์กฐํšŒํ•˜๋˜, ํ‰๊ท  ๋‚˜์ด๊ฐ€ ๋†’์€ ์ˆœ์œผ๋กœ ์กฐํšŒ(์˜ค๋ฆ„์ฐจ์ˆœ) 

SELECT t.name, count(ma.ge) as cnt // 3
FROM Member m LEFT JOIN m.team t // 1
GROUP BY t.name // 2
ORDER BY cnt // 4

SELECT ํ•œ ๊ฒฐ๊ณผ๋ฅผ ORDER BY ํ•˜๊ธฐ ๋•Œ๋ฌธ์— SELECT ์ ˆ์— ๋ณ„์นญ์„ ์‚ฌ์šฉํ•ด์„œ ORDER BY์— ์ ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

ORDER BY์— ์—ฌ๋Ÿฌ ์ปฌ๋Ÿผ์„ ์ ์šฉํ•˜๋Š” ๊ฒฝ์šฐ ๋จผ์ € ์ž‘์„ฑํ•œ ์ปฌ๋Ÿผ๋ช…์„ ์šฐ์„ ์ˆœ์œ„๋กœ ์ •๋ ฌํ•ฉ๋‹ˆ๋‹ค.
SELECT m
FROM Member m
ORDER BY m.age DESC, m.username ASC 

-> age๋ฅผ ๋‚ด๋ฆผ์ฐจ์ˆœ์œผ๋กœ ์ •๋ ฌํ•œ ์ดํ›„์— username์„ ์˜ค๋ฆ„์ฐจ์ˆœ์œผ๋กœ ์ •๋ ฌํ•œ ๊ฒฐ๊ณผ๋ฅผ ๋ฆฌํ„ด 

 

JPQL ์กฐ์ธ

JPQL๋„ ์กฐ์ธ์„ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค. SQL์˜ ์กฐ์ธ๊ณผ ๊ธฐ๋Šฅ์€ ๋™์ผํ•˜์ง€๋งŒ ๋ฌธ๋ฒ•์ด ์กฐ๊ธˆ ๋‹ค๋ฆ…๋‹ˆ๋‹ค. ๋‚ด๋ถ€ ์กฐ์ธ๋ถ€ํ„ฐ ์•Œ์•„๋ด…์‹œ๋‹ค.

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

INNER JOIN

๋‚ด๋ถ€์กฐ์ธ์€ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์—์„œ ๋‘ ๊ฐœ ์ด์ƒ์˜ ํ…Œ์ด๋ธ”์„ ์กฐํ•ฉํ•˜์—ฌ ๊ฒฐ๊ณผ๋ฅผ ์ƒ์„ฑํ•˜๋Š” ์กฐ์ธ์—ฐ์‚ฐ์œผ๋กœ, ์กฐ์ธ ์กฐ๊ฑด์„ ๊ธฐ๋ฐ˜์œผ๋กœ ํ…Œ์ด๋ธ” ๊ฐ„ ์ผ์น˜ํ•˜๋Š” ํ–‰์„ ์„ ํƒํ•ด์„œ ๊ฒฐ๊ณผ๋ฅผ ๋ฆฌํ„ดํ•ฉ๋‹ˆ๋‹ค. 

์˜ˆ๋ฅผ๋“ค์–ด Member์™€ Team ํ…Œ์ด๋ธ”์„ INNER JOIN ํ•  ๊ฒฝ์šฐ, ๋‘ ํ…Œ์ด๋ธ”์˜ ์ผ์น˜ํ•˜๋Š” ํ–‰์ธ ID ๊ฐ€ ๋™์ผํ•œ (MEMBER.member_id = TEAM.team_id) ํ–‰๋งŒ ๊ฒฐ๊ณผ์— ํฌํ•จํ•ด์„œ ๋ฆฌํ„ดํ•ฉ๋‹ˆ๋‹ค.
  • ๋™์ผํ•˜๊ฒŒ INNER JOIN์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ์ฐธ๊ณ ๋กœ INNER๋Š” ์ƒ๋žต ๊ฐ€๋Šฅ.
List<Member> resultList = em.createQuery("SELECT m FROM Member m INNER JOIN m.team t where t.name =: teamName", Member.class)
        .setParameter("teamName", "team1")
        .getResultList();
for (Member member : resultList) {
    System.out.println("member = " + member);
}
  • MEMBER ์™€ TEAM ํ…Œ์ด๋ธ”์—์„œ ๋™์ผํ•œ ID๋ฅผ ๊ธฐ์ค€์œผ๋กœ JOIN ํ•œ ํ›„,  ์ด๋ฆ„ ๊ธฐ๋ฐ˜ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๋ฐ”์ธ๋”ฉ๋œ ๊ฐ’์ธ ํŒ€์ด๋ฆ„์„ ๊ฐ€์ง„ ๋ฉค๋ฒ„ ์กฐํšŒ ์ฟผ๋ฆฌ
  • ๊ฐ€์žฅ ํฐ ํŠน์ง• : SQL ๊ณผ ๋‹ฌ๋ฆฌ ์กฐ์ธํ•  ๋•Œ ์—ฐ๊ด€ ํ•„๋“œ๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. (Member m INNER JOIN m.team t)
JPQL์„ ํ†ตํ•ด ์ƒ์„ฑ ๋˜๋Š” SQL : MEMBER M INNER JOIN TEAM T ON M.TEAM_ID=T.TEAM_ID
  • ์ฃผ์˜ : ์—ฐ๊ด€ ํ•„๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ  JPQL ์กฐ์ธ์„ SQL ์กฐ์ธ ์ฒ˜๋Ÿผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ ๋ฌธ๋ฒ• ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค. 

๋ฌธ๋ฒ• ์˜ค๋ฅ˜ ๋ฐœ์ƒ ์˜ˆ์‹œ

List<Member> resultList = em.createQuery("SELECT m FROM Member m INNER JOIN Team t where t.name =: teamName", Member.class) // SQL ์กฐ์ธ์ฒ˜๋Ÿผ ์‚ฌ์šฉ
        .setParameter("teamName", "team1")
        .getResultList();
for (Member member : resultList) {
    System.out.println("member = " + member);
}

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

LEFT OUTER JOIN

์™ธ๋ถ€ ์กฐ์ธ์€ ๋‚ด๋ถ€ ์กฐ์ธ๊ณผ ๋‹ฌ๋ฆฌ, ์ผ์น˜ํ•˜๋Š” ํ–‰ ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ์ผ์น˜ํ•˜์ง€ ์•Š๋Š” ํ–‰๋„ ๊ฒฐ๊ณผ์— ํฌํ•จ์‹œํ‚ต๋‹ˆ๋‹ค.

  • LEFT JOIN : ์™ผ์ชฝ ํ…Œ์ด๋ธ”์˜ ๋ชจ๋“  ํ–‰๊ณผ ์˜ค๋ฅธ์ชฝ ํ…Œ์ด๋ธ”์—์„œ ์ผ์น˜ํ•˜๋Š” ํ–‰์„ ์กฐํ•ฉํ•˜์—ฌ ๊ฒฐ๊ณผ๋ฅผ ์ƒ์„ฑ. ์ผ์น˜ํ•˜์ง€ ์•Š๋Š” ํ–‰์€ NULL๋กœ ์ฑ„์›Œ์ง
  • RIGHT JOIN :  ๋ฐ˜๋Œ€๋กœ ์˜ค๋ฅธ์ชฝ ํ…Œ์ด๋ธ”์˜ ๋ชจ๋“  ํ–‰๊ณผ ์™ผ์ชฝ ํ…Œ์ด๋ธ”์—์„œ ์ผ์น˜ํ•˜๋Š” ํ–‰์„ ์กฐํ•ฉํ•˜์—ฌ ๊ฒฐ๊ณผ๋ฅผ ์ƒ์„ฑ. ์ผ์น˜ํ•˜์ง€ ์•Š๋Š” ํ–‰์€ NULL๋กœ ์ฑ„์›Œ์ง

JPQL ์™ธ๋ถ€ ์กฐ์ธ ๋˜ํ•œ SQL ์™ธ๋ถ€ ์กฐ์ธ๊ณผ ๋™์ผํ•ฉ๋‹ˆ๋‹ค. LEFT ๋‚˜ RIGHT ์ž‘์„ฑ ์‹œ OUTER ์ƒ๋žต ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

๋ณดํ†ต LEFT JOIN์œผ๋กœ ์‚ฌ์šฉ ํ•ฉ๋‹ˆ๋‹ค.

 

์™ธ๋ถ€ ์กฐ์ธ JPQL ๋˜ํ•œ ์—ฐ๊ด€ํ•„๋“œ๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

List<Member> resultList = em.createQuery("SELECT m FROM Member m LEFT JOIN m.team t where t.name =: teamName", Member.class)
        .setParameter("teamName", "team1")
        .getResultList();
for (Member member : resultList) {
    System.out.println("member = " + member);
}

์ปฌ๋ ‰์…˜ ์กฐ์ธ

์ผ๋Œ€๋‹ค, ๋‹ค๋Œ€๋‹ค ๊ด€๊ณ„์ฒ˜๋Ÿผ ์ปฌ๋ ‰์…˜์„ ์‚ฌ์šฉํ•˜๋Š” ๊ณณ์— ์กฐ์ธํ•˜๋Š” ๊ฒƒ์„ ์ปฌ๋ ‰์…˜ ์กฐ์ธ์ด๋ผ๊ณ ํ•ฉ๋‹ˆ๋‹ค.

 

Member (*) โžก๏ธ Team(1) ์œผ๋กœ์˜ ์กฐ์ธ์€ ๋‹ค๋Œ€์ผ ์กฐ์ธ์ด๋ฉด์„œ ๋‹จ์ผ ๊ฐ’ ์—ฐ๊ด€ ํ•„๋“œ m.team ๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

SELECT m, t
FROM Member m LEFT JOIN m.team

 

๋ฐ˜๋Œ€๋กœ Team(1) โžก๏ธ Member ๋กœ์˜ ์กฐ์ธ์€ ์ผ๋Œ€๋‹ค ์กฐ์ธ์ด๋ฉด์„œ ์ปฌ๋ ‰์…˜ ๊ฐ’ ์—ฐ๊ด€ ํ•„๋“œ m.members๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. 

SELECT t, m 
FROM Team t LEFT JOIN t.members m

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

์„ธํƒ€ ์กฐ์ธ์€ ๋‘˜ ์ด์ƒ์˜ ํ…Œ์ด๋ธ”์„ ์—ฐ๊ฒฐํ•ด์„œ ๊ด€๋ จ๋œ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋Š”๋ฐ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. 

WHERE ์ ˆ์„ ์‚ฌ์šฉํ•ด์„œ ์„ธํƒ€ ์กฐ์ธ์„ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ฐธ๊ณ ๋กœ ๋‚ด๋ถ€ ์„ธํƒ€ ์กฐ์ธ๋งŒ ์ง€์›.

์„ธํƒ€์กฐ์ธ์„ ์‚ฌ์šฉํ•˜๋ฉด ์ „ํ˜€ ๊ด€๊ณ„์—†๋Š” ์—”ํ‹ฐํ‹ฐ๋„ ์กฐ์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

// JPQL
SELECT COUNT(m) 
FROM Member m, Team T
WHERE m.username = t.name

// SQL
SELECT COUNT(M.ID)
FROM MEMBER M CROSS TEAM T
WHERE M.USERNAME=T.NAME

JOIN ON ์ ˆ

JPA 2.1 ์ดํ›„ ๋ฒ„์ „๋ถ€ํ„ฐ๋Š” JOIN ON ์ ˆ์„ ์ง€์›ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์กฐ์ธ ๋Œ€์ƒ์„ ํ•„ํ„ฐ๋งํ•˜๊ณ  ์กฐ์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. 

๋‚ด๋ถ€ ์กฐ์ธ์˜ ON์ ˆ์€ WHERE ์ ˆ์„ ์‚ฌ์šฉํ•  ๋•Œ์™€ ๊ฒฐ๊ณผ๊ฐ€ ๊ฐ™์œผ๋ฏ€๋กœ ๋ณดํ†ต ON ์ ˆ์€ OUTER ์กฐ์ธ์—์„œ๋งŒ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
// JPQL
SELECT m, t
FROM Member m LEFT JOIN m.team t on t.name='A'

// SQL
SELECT m.*, t.* 
FROM Member m LEFT JOIN Team t ON m.TEAM_ID=t.id and t.name = 'A'

ํŽ˜์น˜ ์กฐ์ธ

์—”ํ‹ฐํ‹ฐ๋ฅผ ์กฐํšŒํ•  ๋•Œ ์กฐ์ธํ•œ ์—”ํ‹ฐํ‹ฐ๋‚˜ ์ปฌ๋ ‰์…˜๊นŒ์ง€ ํ•œ ๋ฒˆ์— ๊ฐ™์ด ์กฐํšŒํ•˜๋Š” JPQL๋งŒ์˜ ๊ธฐ๋Šฅ์ž…๋‹ˆ๋‹ค.

 

์ผ๋ฐ˜์ ์ธ join๊ณผ์˜ ์ฐจ์ด์ ์€ ์ผ๋ฐ˜์ ์ธ join์€ ์กฐํšŒ ์‹œ ์กฐํšŒํ•œ ์—”ํ‹ฐํ‹ฐ๋งŒ ๋ฐ˜ํ™˜ํ•˜๊ณ , ์—ฐ๊ด€๋œ ์—”ํ‹ฐํ‹ฐ๋ฅผ ํ•จ๊ป˜ ๋กœ๋“œํ•˜์ง€๋Š” ์•Š์Šต๋‹ˆ๋‹ค.

๋ฐ˜๋ฉด, fetch join์€ ์—ฐ๊ด€๋œ ์—”ํ‹ฐํ‹ฐ๋„ ํ•จ๊ป˜ ์กฐํšŒํ•จ์œผ๋กœ์จ ์ง€์—ฐ๋กœ๋”ฉํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹Œ ์ฆ‰์‹œ๋กœ๋”ฉํ•œ๋‹ค๋Š” ์ ์ž…๋‹ˆ๋‹ค. 

 

์ฆ‰์‹œ๋กœ๋”ฉํ•˜๋ฉด ์žฅ์ ์ด ๋ญ๋ƒ ?  ํ›„์† ์ฟผ๋ฆฌ( ์—ฐ๊ด€๋œ ์—”ํ‹ฐํ‹ฐ๋ฅผ ๋กœ๋“œํ•˜๊ธฐ ์œ„ํ•ด ์ถ”๊ฐ€์ ์œผ๋กœ ์‹คํ–‰๋˜๋Š” ์ฟผ๋ฆฌ)๋ฅผ ๋ณ„๋„๋กœ ์‚ฌ์šฉํ•˜์ง€ ์•Š์•„๋„ ๋œ๋‹ค!

 

์—”ํ‹ฐํ‹ฐ ํŽ˜์น˜ ์กฐ์ธ

MEMBER INNER JOIN FETCH TEAM

ํšŒ์› ์—”ํ‹ฐํ‹ฐ๋ฅผ ์กฐํšŒํ•˜๋ฉด์„œ ์—ฐ๊ด€๋œ ํŒ€ ์—”ํ‹ฐํ‹ฐ๋„ ํ•จ๊ป˜ ์กฐํšŒํ•˜๋Š” JPQL

SELECT m
FROM Member m INNER JOIN FETCH m.team

JOIN ์˜†์— FETCH ํ‚ค์›Œ๋“œ๋ฅผ ๋ถ™์ด๋ฉด ์—ฐ๊ด€๋œ ์—”ํ‹ฐํ‹ฐ๋‚˜ ์ปฌ๋ ‰์…˜์„ ํ•จ๊ป˜ ์กฐํšŒํ•ฉ๋‹ˆ๋‹ค. ์ฐธ๊ณ ๋กœ ์ผ๋ฐ˜์ ์ธ JPQL ์กฐ์ธ๊ณผ ๋‹ค๋ฅด๊ฒŒ ํŽ˜์น˜ ์กฐ์ธ์—์„œ๋Š” ๋ณ„์นญ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. 

 

์‹คํ–‰๋œ SQL

SELECT M.*, T.*
FROM MEMBER M INNER JOIN TEAM T ON M.TEAM_ID = T.ID
  • JPQL์—์„œ m ๋งŒ SELECT ํ–ˆ์ง€๋งŒ , SQL์„ ๋ณด๋ฉด M๋ฟ๋งŒ ์•„๋‹ˆ๋ผ T๊นŒ์ง€ SELECT ๋œ ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ์—”ํ‹ฐํ‹ฐ๋ฅผ ์ง€์—ฐ๋กœ๋”ฉ์œผ๋กœ ์„ค์ •ํ–ˆ๋‹ค ํ•˜๋”๋ผ๋„ ํŽ˜์น˜ ์กฐ์ธ์„ ํ•˜๊ฒŒ ๋˜๋ฉด ์—ฐ๊ด€๋œ ์—”ํ‹ฐํ‹ฐ T๋Š” ํ”„๋ก์‹œ๊ฐ€ ์•„๋‹Œ ์‹ค์ œ ์—”ํ‹ฐํ‹ฐ์ด๊ธฐ ๋•Œ๋ฌธ์— ์ง€์—ฐ ๋กœ๋”ฉ์ด ์ผ์–ด๋‚˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
  • ์ถ”๊ฐ€์ ์œผ๋กœ ์‹ค์ œ ์—”ํ‹ฐํ‹ฐ์ด๊ธฐ ๋•Œ๋ฌธ์— ํšŒ์› ์—”ํ‹ฐํ‹ฐ๊ฐ€ ์ค€์˜์†์ƒํƒœ๊ฐ€ ๋˜์–ด๋„ ์—ฐ๊ด€๋œ ํŒ€์„ ์กฐํšŒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ปฌ๋ ‰์…˜ ํŽ˜์น˜ ์กฐ์ธ

TEAM INNER JOIN FETCH MEMBER

์ด๋ฒˆ์—๋Š” Team๊ณผ ์ผ๋Œ€๋‹ค ๊ด€๊ณ„์ธ Member ์ปฌ๋ ‰์…˜์„ ํŽ˜์น˜ ์กฐ์ธํ•ด ๋ด…์‹œ๋‹ค.

 

ํŒ€ ์—”ํ‹ฐํ‹ฐ๋ฅผ ์กฐํšŒํ•˜๋ฉด์„œ ์—ฐ๊ด€๋œ ๋ฉค๋ฒ„ ์—”ํ‹ฐํ‹ฐ(์ปฌ๋ ‰์…˜)๋„ ํ•จ๊ป˜ ์กฐํšŒํ•˜๋Š” JPQL

SELECT t
FROM Team t INNER JOIN FETCH t.members

์‹คํ–‰๋œ SQL

SELECT T.*, M.*
FROM TEAM T INNER JOIN FETCH MEMBER M ON T.id = M.team_id
  • ์—”ํ‹ฐํ‹ฐ ํŽ˜์น˜ ์กฐ์ธ๊ณผ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ JPQL์—์„œ t๋งŒ ํŽ˜์น˜ ์กฐ์ธ ํ›„ select ํ•ด๋„ SQL์—์„œ t๋ฟ๋งŒ ์•„๋‹ˆ๋ผ m๊นŒ์ง€ ํ•จ๊ป˜ select ๋œ ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
public static void main(String[] args) {
    EntityManagerFactory emf = Persistence.createEntityManagerFactory("jpql");
    EntityManager em = emf.createEntityManager();
    EntityTransaction tx = em.getTransaction();

    tx.begin();

    try {
        List<Team> resultList = em.createQuery("SELECT t FROM Team t INNER JOIN FETCH t.members", Team.class)
                .getResultList();
        for (Team team : resultList) {
            System.out.println("team = " + team);
        }
    } catch (Exception e) {
        tx.rollback();
    }finally {
        em.close();
    }

    emf.close();
}
  • ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ์‹ค์ œ ์—”ํ‹ฐํ‹ฐ๋ฅผ ์กฐํšŒํ•˜๋Š” ๊ฒƒ์ด๊ธฐ ๋•Œ๋ฌธ์— ๊ฐ™์€ ํŒ€์— ์†Œ์†๋œ ํšŒ์›๋“ค์€ ์ฐธ์กฐ๊ฐ€ ๋™์ผํ•œ ํŒ€ ์—”ํ‹ฐํ‹ฐ๋ฅผ ๊ฐ–์Šต๋‹ˆ๋‹ค.
    • team = domain.Team@313f8301
      team = domain.Team@313f8301
  • DISTINCT FETCH JOIN์„ ํ•˜๋ฉด ์ค‘๋ณต๋˜๋Š” ํŒ€ ์—”ํ‹ฐํ‹ฐ๋Š” ํ•˜๋‚˜๋งŒ ์กฐํšŒ๋ฉ๋‹ˆ๋‹ค.
    • team = domain.Team@313f8301

 

ํŽ˜์น˜ ์กฐ์ธ ์žฅ์ 

  1. ํŽ˜์น˜์กฐ์ธ์„ ์‚ฌ์šฉํ•˜๋ฉด ์—ฐ๊ด€๋œ ์—”ํ‹ฐํ‹ฐ๋ฅผ ์ฟผ๋ฆฌ ์‹œ์ ์— ์กฐํšŒํ•˜๋ฏ€๋กœ ์ง€์—ฐ ๋กœ๋”ฉ์ด ๋ฐœ์ƒํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
    1. ์ค€์˜์† ์ƒํƒœ์—์„œ๋„ ๊ฐ์ฒด ๊ทธ๋ž˜ํ”„ ํƒ์ƒ‰์ด ๊ฐ€๋Šฅ
  2. SQL ํ˜ธ์ถœ ํšŸ์ˆ˜๋ฅผ ์ค„์—ฌ ์„ฑ๋Šฅ์„ ์ตœ์ ํ™”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. 
  3. ์—”ํ‹ฐํ‹ฐ๊ฐ€ ์ง€์—ฐ๋กœ๋”ฉ(fetchType.LAZY)์œผ๋กœ ์„ค์ •๋˜์–ด ์žˆ๋‹ค ํ•˜๋”๋ผ๋„, ์—ฐ๊ด€๊ด€๊ณ„๋ฅผ ๊ณ ๋ คํ•˜์—ฌ ์—ฐ๊ด€๋œ ์—”ํ‹ฐํ‹ฐ๊นŒ์ง€ ์กฐํšŒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
    1. ํŽ˜์น˜ ์กฐ์ธ์€ ๊ธ€๋กœ๋ฒŒ ๋กœ๋”ฉ ์ „๋žต ๋ณด๋‹ค ์šฐ์„ ์‹œ๋ฉ๋‹ˆ๋‹ค. ๊ทธ๋ ‡๊ธฐ ๋•Œ๋ฌธ์— ํŽ˜์น˜ ํƒ€์ž…์„ LAZY๋กœ ์„ค์ •ํ•˜๋”๋ผ๋„ ํŽ˜์น˜ ์กฐ์ธ์„ ์‚ฌ์šฉํ•˜๋ฉด ๋ฐ์ดํ„ฐ๊ฐ€ ์ฆ‰์‹œ ์กฐํšŒ๋˜๋Š” ๊ฒฐ๊ณผ๋ฅผ ๊ฐ€์ ธ์˜ค๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.
    2. ๊ธ€๋กœ๋ฒŒ ๋กœ๋”ฉ ์ „๋žต์€ ๋  ์ˆ˜ ์žˆ์œผ๋ฉด ์ง€์—ฐ ๋กœ๋”ฉ์„ ์‚ฌ์šฉํ•˜๊ณ  ์ตœ์ ํ™”๊ฐ€ ํ•„์š”ํ•˜๋ฉด ํŽ˜์น˜ ์กฐ์ธ์„ ์ ์šฉํ•˜๋Š” ๊ฒƒ์ด ํšจ๊ณผ์ ์ž…๋‹ˆ๋‹ค.

ํŽ˜์น˜ ์กฐ์ธ ํ•œ๊ณ„์ 

  1. ์กฐ์ธ ๋Œ€์ƒ์— ๋ณ„์นญ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.
    1. ํ•˜์ง€๋งŒ ! ํ•˜์ด๋ฒ„๋„ค์ดํŠธ๋Š” ํŽ˜์น˜ ์กฐ์ธ์—๋„ ๋ณ„์นญ์„ ํ—ˆ์šฉํ•ฉ๋‹ˆ๋‹ค. 
  2. ๋‘˜ ์ด์ƒ์˜ ์ปฌ๋ ‰์…˜์„ ํŽ˜์น˜ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.
    1. ๊ตฌํ˜„์ฒด์— ๋”ฐ๋ผ ๋˜๊ธฐ๋„ ํ•˜์ง€๋งŒ ์ปฌ๋ ‰์…˜ * ์ปฌ๋ ‰์…˜์˜ ๊ฒฝ์šฐ Cartesian Product ๊ฐ€ ๋งŒ๋“ค์–ด ์ง€๋ฏ€๋กœ ์ฃผ์˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
  3. ํŽ˜์น˜ ์กฐ์ธ์„ ์‚ฌ์šฉํ•˜๋ฉด ํŽ˜์ด์ง• API๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

<์ฐธ๊ณ ์ž๋ฃŒ>

 

SQL ์™ผ์ชฝ ์กฐ์ธ - ์ œํƒ€์œ„ํ‚ค

๋‹ค์Œ ๋ฌธ์ž์—ด ํฌํ•จ...

zetawiki.com

 

SQL ๋‚ด๋ถ€ ์กฐ์ธ - ์ œํƒ€์œ„ํ‚ค

๋‹ค์Œ ๋ฌธ์ž์—ด ํฌํ•จ...

zetawiki.com

 

 

[JPA] ํŽ˜์น˜ ์กฐ์ธ(fetch join)์ด๋ž€?

SQL์„ ์‚ฌ์šฉํ•  ๋•Œ ์—ฐ๊ด€๊ด€๊ณ„๊ฐ€ ์žˆ๋Š” ๋‹ค๋ฅธ ํ…Œ์ด๋ธ”์˜ ์ •๋ณด๋ฅผ ์ด์šฉํ•˜๋ ค๊ณ  ํ•œ๋‹ค๋ฉด JOIN์„ ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. INNER JOIN, OUTER JOIN๊ณผ ๊ฐ™์€ JOIN ํ˜•ํƒœ๊ฐ€ ์กด์žฌํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ ‡๋‹ค๋ฉด FETCH JOIN์€ ๋ฌด์—‡์„ ์˜๋ฏธํ• ๊นŒ์š”? Fetch

woo-chang.tistory.com

 

๋ธ”๋กœ๊ทธ์˜ ์ •๋ณด

Study Repository

rlaehddnd0422

ํ™œ๋™ํ•˜๊ธฐ