๐ŸŒป JAVA/์ž๋ฐ” ORM ํ‘œ์ค€ JPA ํ”„๋กœ๊ทธ๋ž˜๋ฐ

๐ŸŒป JAVA/์ž๋ฐ” ORM ํ‘œ์ค€ JPA ํ”„๋กœ๊ทธ๋ž˜๋ฐ

JPA - Fetch Join์ด ๊ณผ์—ฐ ๋งŒ๋Šฅ์ธ๊ฐ€? (N+1, Pagination)

๋“ค์–ด๊ฐ€๊ธฐ ์ „ ์ด์ „ ์‹œ๊ฐ„์— ์•Œ์•„๋ดค๋˜ N+1 ํ•ด๊ฒฐ๋ฒ•์— ์ด์–ด์„œ FetchJoin์„ ์ด์šฉํ•ด์„œ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ Fetch Join์ด๋ผ๊ณ  ๋‹ค ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์€ ์•„๋‹™๋‹ˆ๋‹ค. ์ด๋ฒˆ ์‹œ๊ฐ„์—๋Š” Fetch Join์„ ์‚ฌ์šฉํ–ˆ์„ ๋•Œ ์–ด๋– ํ•œ ์‚ฌ์ด๋“œ ์ดํŽ™ํŠธ๊ฐ€ ์žˆ๋Š”์ง€ ์•Œ์•„๋ณด๊ณ  ๊ทธ ํ•ด๊ฒฐ์ฑ…์— ๋Œ€ํ•ด์„œ ์•Œ์•„๋ด…๋‹ˆ๋‹ค. 1. FetchJoin, EntityGraph ์‚ฌ์šฉ ์‹œ Pagination์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๋‹ค. FetchJoin๊ณผ EntityGraph ๋‘˜ ๋‹ค ๋™์ผํ•œ ์ฆ์ƒ์ด ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค. Fetch Join๋งŒ ํ…Œ์ŠคํŠธ๋ฅผ ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. @Query( value = "select t from Team t join fetch t.members", countQuery = "select count(t) from Team t" ) List f..

๐ŸŒป JAVA/์ž๋ฐ” ORM ํ‘œ์ค€ JPA ํ”„๋กœ๊ทธ๋ž˜๋ฐ

[JPA] N+1 ๋ฌธ์ œ์™€ ํ•ด๊ฒฐ (feat. fetch join, EntityGraph)

๐Ÿ’ก ์•„๋ž˜ ์‹ค์Šต์— ์ง„ํ–‰ํ•œ ๋ชจ๋“  ์ฝ”๋“œ๋Š” Github์— ์žˆ์Šต๋‹ˆ๋‹ค. JPA N+1์ด๋ž€? ์‹ค๋ฌด์—์„œ JPA๋ฅผ ์‚ฌ์šฉํ•˜๋‹ค๋ณด๋ฉด, N+1 ์ฟผ๋ฆฌ๋ฅผ ๋งŒ๋‚˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์„œ N+1์ด๋ž€ Team(1) โ†” Member(N) ์—ฐ๊ด€๊ด€๊ณ„๊ฐ€ ์žˆ๋‹ค๊ณ  ๊ฐ€์ •ํ–ˆ์„ ๋•Œ, ํ•˜๋‚˜์˜ ํŒ€์„ ์กฐํšŒํ–ˆ์ง€๋งŒ ํŒ€ ๋‚ด๋ถ€์— ์žˆ๋Š” ๋ชจ๋“  ๋ฉค๋ฒ„๋“ค์ด ํ•จ๊ป˜ ์กฐํšŒ๋˜๋ฉด์„œ 1+N ๊ฐœ์˜ ์ฟผ๋ฆฌ๊ฐ€ ๋ฐœ์ƒํ•˜๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. ์ง์ ‘ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋ฅผ ํ†ตํ•ด ์ด๋Ÿฌํ•œ ์ƒํ™ฉ๋“ค์„ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•๋“ค์„ ์‚ดํŽด๋ณด๊ณ  ๊ฐ ์ƒํ™ฉ์ด ๋˜ ์–ด๋–ค ์‚ฌ์ด๋“œ์ดํŽ™ํŠธ๊ฐ€ ์žˆ๋Š”์ง€๋„ ์•Œ์•„๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. Entity ๋ฐ Repository ์ฝ”๋“œ ์‹ค์Šต์— ์‚ฌ์šฉ๋  ์ฝ”๋“œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค. @Getter @NoArgsConstructor(access = AccessLevel.PROTECTED) @Entity public class Membe..

๐ŸŒป JAVA/์ž๋ฐ” ORM ํ‘œ์ค€ JPA ํ”„๋กœ๊ทธ๋ž˜๋ฐ

CascadeType.DELETE, orphanRemoval ์ฐจ์ด์ 

CascadeType.DELETE, orphanRemoval ์ฐจ์ด์  ๋ชฉํ‘œ CASCADE.REMOVE ์™€ orphanRemoval์˜ ์ฐจ์ด์ ์— ๋Œ€ํ•ด์„œ ์•Œ์•„๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ํ…Œ์ŠคํŠธ์šฉ ์—”ํ‹ฐํ‹ฐ public class Parent { @OneToMany(mappedBy = "parent") private List children = new ArrayList(); } public class Child { @ManyToOne @JoinColumn(name = "PARENT_ID") private Parent parent; } CASCADE.REMOVE @OneToMany(mappedBy = "parent", cascade = CascadeType.REMOVE) private List children = new ArrayLi..

๐ŸŒป JAVA/์ž๋ฐ” ORM ํ‘œ์ค€ JPA ํ”„๋กœ๊ทธ๋ž˜๋ฐ

LazyInitializationException์ด ๋‚˜๋Š” ์ด์œ  (feat. ํŠธ๋žœ์žญ์…˜)

์ฝ”๋“œ ์ „์ฒด ์ฝ”๋“œ๋Š” Github์— ์žˆ์Šต๋‹ˆ๋‹ค :) TeamServiceTest @RunWith(SpringRunner.class) @SpringBootTest public class TeamServiceTest { @Autowired private TeamService teamService; @Before public void setup() { Team team = new Team(null, "team", new ArrayList()); for (int i = 1; i t.getMembers().get(0).getName()); } } TeamRepository @Repository public interface TeamRepository extends JpaRepository { } ์ƒํ™ฉ Serivce๋‹จ์—..

๐ŸŒป JAVA/์ž๋ฐ” ORM ํ‘œ์ค€ JPA ํ”„๋กœ๊ทธ๋ž˜๋ฐ

10-3) JPQL - ์ค‘๊ธ‰ ๋ฌธ๋ฒ•

์ž๋ฐ” ORM ํ‘œ์ค€ JPA ํ”„๋กœ๊ทธ๋ž˜๋ฐ - ๊ธฐ๋ณธํŽธ์„ ๊ณต๋ถ€ํ•˜๋ฉฐ ์ •๋ฆฌํ•œ ๋‚ด์šฉ์ž…๋‹ˆ๋‹ค. ์ž๋ฐ” ORM ํ‘œ์ค€ JPA ํ”„๋กœ๊ทธ๋ž˜๋ฐ - ๊ธฐ๋ณธํŽธ - ์ธํ”„๋Ÿฐ JPA๋ฅผ ์ฒ˜์Œ ์ ‘ํ•˜๊ฑฐ๋‚˜, ์‹ค๋ฌด์—์„œ JPA๋ฅผ ์‚ฌ์šฉํ•˜์ง€๋งŒ ๊ธฐ๋ณธ ์ด๋ก ์ด ๋ถ€์กฑํ•˜์‹  ๋ถ„๋“ค์ด JPA์˜ ๊ธฐ๋ณธ ์ด๋ก ์„ ํƒ„ํƒ„ํ•˜๊ฒŒ ํ•™์Šตํ•ด์„œ ์ดˆ๋ณด์ž๋„ ์‹ค๋ฌด์—์„œ ์ž์‹ ์žˆ๊ฒŒ JPA๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ดˆ๊ธ‰ ์›น ๊ฐœ๋ฐœ ํ”„๋กœ๊ทธ๏ฟฝ www.inflearn.com ๋ชฉ์ฐจ ๊ฒฝ๋กœ ํ‘œํ˜„์‹ ํŽ˜์น˜ ์กฐ์ธ 1 - ๊ธฐ๋ณธ ํŽ˜์น˜ ์กฐ์ธ 2 - ํ•œ๊ณ„ ๋‹คํ˜•์„ฑ ์ฟผ๋ฆฌ ์—”ํ‹ฐํ‹ฐ ์ง์ ‘ ์‚ฌ์šฉ Named ์ฟผ๋ฆฌ ๋ฒŒํฌ ์—ฐ์‚ฐ ๊ฒฝ๋กœ ํ‘œํ˜„์‹ (์‹ค๋ฌด์—์„œ ์‚ฌ์šฉ ๊ถŒ์žฅ X) ( ๊ฒฝ๋กœ ํ‘œํ˜„์‹์œผ๋กœ ์ธํ•ด ๋ฌต์‹œ์ ์œผ๋กœ SQL ์กฐ์ธ(๋‚ด๋ถ€ ์กฐ์ธ) ๋ฐœ์ƒ) - ๋‚˜์ค‘์— ํฐ ํ˜ผ๋ž€์„ ์ค„ ์ˆ˜ ์žˆ์Œ. ๊ฒฝ๋กœ ํ‘œํ˜„์‹์ด๋ž€ ? .(์ )์„ ์ฐ์–ด ๊ฐ์ฒด ๊ทธ๋ž˜ํ”„๋ฅผ ํƒ์ƒ‰ํ•˜๋Š” ๊ฒƒ Member mem..

๐ŸŒป JAVA/์ž๋ฐ” ORM ํ‘œ์ค€ JPA ํ”„๋กœ๊ทธ๋ž˜๋ฐ

10-2) JPQL - ๊ธฐ๋ณธ ๋ฌธ๋ฒ•๊ณผ ๊ธฐ๋Šฅ

์ž๋ฐ” ORM ํ‘œ์ค€ JPA ํ”„๋กœ๊ทธ๋ž˜๋ฐ - ๊ธฐ๋ณธํŽธ์„ ๊ณต๋ถ€ํ•˜๋ฉฐ ์ •๋ฆฌํ•œ ๋‚ด์šฉ์ž…๋‹ˆ๋‹ค. ์ž๋ฐ” ORM ํ‘œ์ค€ JPA ํ”„๋กœ๊ทธ๋ž˜๋ฐ - ๊ธฐ๋ณธํŽธ - ์ธํ”„๋Ÿฐ JPA๋ฅผ ์ฒ˜์Œ ์ ‘ํ•˜๊ฑฐ๋‚˜, ์‹ค๋ฌด์—์„œ JPA๋ฅผ ์‚ฌ์šฉํ•˜์ง€๋งŒ ๊ธฐ๋ณธ ์ด๋ก ์ด ๋ถ€์กฑํ•˜์‹  ๋ถ„๋“ค์ด JPA์˜ ๊ธฐ๋ณธ ์ด๋ก ์„ ํƒ„ํƒ„ํ•˜๊ฒŒ ํ•™์Šตํ•ด์„œ ์ดˆ๋ณด์ž๋„ ์‹ค๋ฌด์—์„œ ์ž์‹ ์žˆ๊ฒŒ JPA๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ดˆ๊ธ‰ ์›น ๊ฐœ๋ฐœ ํ”„๋กœ๊ทธ๏ฟฝ www.inflearn.com ๋ชฉ์ฐจ JPQL ์†Œ๊ฐœ ํ”„๋กœ์ ์…˜(SELECT) ํŽ˜์ด์ง• ์กฐ์ธ ์„œ๋ธŒ์ฟผ๋ฆฌ JPQL ํƒ€์ž… ํ‘œํ˜„๊ณผ ๊ธฐํƒ€์‹ ์กฐ๊ฑด์‹(CASE ๋“ฑ๋“ฑ) JPQL ํ•จ์ˆ˜ ๐Ÿ—’ JPQL ์†Œ๊ฐœ JPQL์€ ๊ฐ์ฒด์ง€ํ–ฅ ์ฟผ๋ฆฌ ์–ธ์–ด์ด๋‹ค. ๋”ฐ๋ผ์„œ ํ…Œ์ด๋ธ”์„ ๋Œ€์ƒ์œผ๋กœ ์ฟผ๋ฆฌํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ ์—”ํ‹ฐํ‹ฐ ๊ฐ์ฒด๋ฅผ ๋Œ€์ƒ์œผ๋กœ ์ฟผ๋ฆฌํ•œ๋‹ค. JPQL์€ SQL์„ ์ถ”์ƒํ™”ํ•ด์„œ ํŠน์ • ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค SQL์— ์˜์กดํ•˜์ง€ ์•Š๋Š”๋‹ค. JPQ..

iseunghan
'๐ŸŒป JAVA/์ž๋ฐ” ORM ํ‘œ์ค€ JPA ํ”„๋กœ๊ทธ๋ž˜๋ฐ' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๊ธ€ ๋ชฉ๋ก