coding/Java, Spring

JPA _ proxy, eager loading, lazyloading

Jeo 2022. 2. 21. 19:54

๐Ÿ“ ์ž๋ฐ” ORM ํ‘œ์ค€ JPA ํ”„๋กœ๊ทธ๋ž˜๋ฐ - ๊น€์˜ํ•œ๋‹˜ ๊ฐ•์˜๋ฅผ ๋“ค์œผ๋ฉด์„œ ํ•„๊ธฐ!

 

๐Ÿค”โ“ ๋ฌธ์ œ์˜์‹

Member์™€ Team์ด ์—ฐ๊ด€ ๋งคํ•‘์ด ๋˜์–ด ์žˆ๋‹ค๊ณ  ํ•˜์ž. 

๊ทธ๋Ÿผ Member๊ฐ€ ์กฐํšŒ๋  ๋•Œ๋งˆ๋‹ค ๊ทธ ์•ˆ์—์„œ ์ฐธ์กฐ๋˜๋Š” Team๋„ ๋ชจ๋‘ ํ•จ๊ป˜ ๊ณง์žฅ ์กฐํšŒ๋˜์–ด์•ผ ํ• ๊นŒ?

์•„๋‹ˆ๋ฉด ํ•„์š”ํ•  ๋•Œ๊ฐ€ ๋˜์–ด์„œ์•ผ Team์„ ๋”ฐ๋กœ ๋ถˆ๋Ÿฌ๋‚ด๋Š” ๊ฒƒ์ด ์ข‹์„๊นŒ?

 

๐Ÿ‘‰ ๊ฐ„๋‹จํ•œ ๋‹ต์€, ๋ฌด์—‡์ด ๋” ๋‚˜์€์ง€์— ๋Œ€ํ•œ ํŒ๋‹จ์€ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์— ๋”ฐ๋ผ ๋‹ค๋ฅด๋‹ค!

(1) ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง ๋Œ€๋ถ€๋ถ„์˜ ๊ฒฝ์šฐ์— Member ์ถœ๋ ฅ์‹œ ๊ฑฐ์˜ Team๋„ ํ•จ๊ป˜ ํ˜ธ์ถœํ•œ๋‹ค๋ฉด?

    => ํ•œ๋ฒˆ์— ๋ชจ๋‘ ๋•ก๊ฒจ์˜ค๋Š” ๊ฒƒ์ด ๋‚ซ๋‹ค.

(2) ๊ทธ๋ ‡์ง€ ์•Š๋‹ค๋ฉด?

   => ๋”ฐ๋กœ ๋”ฐ๋กœ ๋ถˆ๋Ÿฌ์˜ฌ ์ˆ˜ ์žˆ๋„๋ก ํ•˜๋Š” ๊ฒƒ์ด ๋‚ซ๋‹ค.

        (์˜ˆ๋ฅผ ๋“ค์–ด Member๋งŒ ํ•„์š”ํ•˜๊ณ  Team๊นŒ์ง€๋Š” ์•ˆ ํ•„์š”ํ•œ๋ฐ๋„ ๊ตณ์ด ๋‹ค ๋ถˆ๋Ÿฌ์˜ค๋Š” ๊ฒƒ์€ ๋น„ํšจ์œจ์ ์ด๋‹ˆ๊นŒ)

 

๐Ÿ‘‰ ๊ทธ๋Ÿฐ๋ฐ ์ด๋Ÿฐ ํ•„์š”์— ๋”ฐ๋ผ ์šฐ๋ฆฌ๊ฐ€ ๋‹ค๋ฅธ ์„ ํƒ/์ฒ˜๋ฆฌ๋ฅผ ํ•  ์ˆ˜ ์žˆ์„๊นŒ?

     ๊ทธ๋ ‡๋‹ค! JPA์— ์˜ํ•ด ๊ฐ€๋Šฅํ•˜๋‹ค.

     ์–ด๋–ป๊ฒŒ? JPA์—์„œ ์—ฐ๊ด€๋งคํ•‘ํ•œ column์— fetch์˜ต์…˜์„ ์คŒ์œผ๋กœ์จ!

 

(1) LAZY - ์ง€์—ฐ ๋กœ๋”ฉ

@ManyToOne(fetch = FetchType.LAZY)

@JoinColumn(name="TEAM_ID")

private Team team;

  • ์ด ๊ฒฝ์šฐ์—๋Š” team ์„ ํ”„๋ก์‹œ(๊ฐ€์งœ)๋กœ ๋ถˆ๋Ÿฌ๋‹ค ๋†“๊ณ , ์ดํ›„์— team ๋‚ด๋ถ€์— ์‹ค์ œ ๊ฐ’๋“ค์„ ์กฐํšŒํ•˜๋Š” ๋“ฑ ํ˜ธ์ถœํ•  ๋•Œ(ex. team.getName() ๋“ฑ)์—์„œ์•ผ ์‹ค์ œ ๊ฐ’๋“ค์ด ๊ป๋ฐ๊ธฐ๋งŒ ์žˆ๋˜ team์— ์ฑ„์›Œ์ง€๋Š” ๊ฒƒ(์ดˆ๊ธฐํ™”).

 

(2) EAGER - ์ฆ‰์‹œ ๋กœ๋”ฉ (Default)

@ManyToOne(fetch = FetchType.EAGER)

@JoinColumn(name="TEAM_ID")

private Team team;

 

๐Ÿค” ๊ทธ๋ ‡๋‹ค๋ฉด ์‹ค๋ฌด์—์„œ ๋ฌด์—‡์„ ์จ์•ผ ํ• ๊นŒ?

๐Ÿ‘‰ ๊ฐ€๊ธ‰์  ์ง€์—ฐ๋กœ๋”ฉ๋งŒ ์‚ฌ์šฉ!!

์ฆ‰์‹œ ๋กœ๋”ฉ์„ ์‚ฌ์šฉํ•  ๋•Œ ๋ฐœ์ƒํ•˜๋Š” ๋ฌธ์ œ: "JPQL์—์„œ์˜ N+1 ๋ฌธ์ œ"

์‹ค๋ฌด์—์„œ๋Š” JPQL์„ ๋งŽ์ด ์‚ฌ์šฉํ•œ๋‹ค๊ณ  ํ•œ๋‹ค. ๋ณต์žกํ•œ ์ฟผ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜๊ฒŒ ๋˜๋‹ˆ๊นŒ.

๊ทธ๋Ÿฐ๋ฐ JPQL์€ SQL๋กœ ๋ฒˆ์—ญ์ด ๋œ๋‹ค. ๊ทธ๋ ‡๊ธฐ ๋•Œ๋ฌธ์— Team ๊ฐ์ฒด๋ฅผ ์ฐธ์กฐํ•˜๋Š” Member์— ๋Œ€ํ•œ ์ฟผ๋ฆฌ๋ฅผ ๋‚ ๋ฆฌ๋ฉด?

์ผ๋‹จ SQL๋ฌธ์€ member๋งŒ selectํ•  ๊ฒƒ์ด๋‹ค.

๊ทธ๋Ÿฐ๋ฐ ๊ฐ€์ ธ์™€๋ดค๋”๋‹ˆ, Team์ด ์ฆ‰์‹œ ๋กœ๋”ฉ์œผ๋กœ ๋˜์–ด์žˆ๋„ค? ๊ทธ๋ž˜์„œ ์–ด์„œ Team์— ๋Œ€ํ•œ query๋„ ๋‹ค์‹œ ๋ณด๋ƒ„.

์ฆ‰, N+1์˜ ๋ฌธ์ œ๋ž€, ์ตœ์ดˆ์˜ ์ฟผ๋ฆฌ 1๋ฟ๋งŒ ์•„๋‹ˆ๋ผ N๊ฐœ์˜ ์ฟผ๋ฆฌ๋ฅผ ๋” ์‹คํ–‰ํ•˜๊ฒŒ ๋œ๋‹ค๋Š” ๊ฒƒ.

๊ทธ๋ž˜์„œ ๋Œ€๋ถ€๋ถ„์˜ ๊ฒฝ์šฐ FetchType.LAZY ๋กœ ์„ค์ •ํ•œ๋‹ค๊ณ  ํ•จ!

๋‹ค๋งŒ ์‹ค๋ฌด์—์„œ ์–ด๋–ค ๊ฒฝ์šฐ๋Š” ์—ฐ๊ด€ ์—”ํ„ฐํ‹ฐ๋“ค์„ ํ•œ๋ฒˆ์— ๊ฐ™์ด ๊ฐ€์ ธ์˜ค๊ณ  ์‹ถ์„ ์ˆ˜ ์žˆ์Œ. ์ด๋Ÿด ๋•Œ๋Š” ๊ธฐ๋ณธ ์„ธํŒ…์€ FetchType.LAZY๋กœ ํ•˜๋˜ FetchJoin์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค๊ณ  ํ•จ.

 

โœš ๐Ÿค“ ์–ด๋–ป๊ฒŒ ๊ฐ€๋Šฅํ• ๊นŒ?

JPA์˜ ์˜์†์„ฑ ์ปจํ…์ŠคํŠธ๋ฅผ ๋‹ค๋ฃจ๋Š” EntityManager๊ฐ€ ๊ฐ€์ง„ ๋ฉ”์†Œ๋“œ ์ค‘ ๋‹ค์Œ์˜ ๋‘ ๊ฐ€์ง€๋ฅผ ๋น„๊ตํ•ด๋ณด์ž.

EntityManager em;

  1. em.find() : ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ํ†ตํ•ด์„œ ์‹ค์ œ entity ๊ฐ์ฒด ์กฐํšŒ
  2. em.getReference() : ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์กฐํšŒ๋ฅผ ๋ฏธ๋ฃจ๋Š” ๊ฐ€์งœ(ํ”„๋ก์‹œ) entity ์กฐํšŒ
    • getReference()๋กœ ๊ฐ€์ ธ์˜ค๋Š” proxy๋Š” ์‹ค์ œ entity๋ฅผ ์ƒ์†๋ฐ›์•„ ๋งŒ๋“ค์–ด์ ธ์„œ, ๊ป๋ฐ๊ธฐ๋Š” ๊ฐ™๋‹ค.