๐Ÿ๏ธ Spring/JPA

์Šคํ”„๋ง์—์„œ JPA๋ฅผ ์‚ฌ์šฉํ•˜๊ฒŒ ๋˜๋ฉด ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ๊ฐ€ ํŠธ๋žœ์žญ์…˜๊ณผ ์˜์†์„ฑ ์ปจํ…์ŠคํŠธ๋ฅผ ๊ด€๋ฆฌํ•ด์ฃผ๋ฏ€๋กœ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์†์‰ฝ๊ฒŒ ๊ฐœ๋ฐœํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋‹น์—ฐํ•˜๊ฒŒ๋„ ์ด๋Ÿฌํ•œ JPA์˜ ๋‚ด๋ถ€ ๋™์ž‘์›๋ฆฌ๋ฅผ ๋ชจ๋ฅด๊ณ  ์‚ฌ์šฉํ•œ๋‹ค๋ฉด ์—ฌ๋Ÿฌ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ–ˆ์„ ๋•Œ ํ•ด๊ฒฐํ•˜๊ธฐ ์–ด๋ ต์Šต๋‹ˆ๋‹ค. ์ด๋ฒˆ ๊ธ€์„ ํ†ตํ•ด JPA๊ฐ€ ๋™์ž‘ํ•˜๋Š” ๋‚ด๋ถ€ ๋ฐฉ์‹์„ ์ดํ•ดํ•˜๊ณ , ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๊ฐœ๋ฐœํ•  ๋•Œ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋Š” ๋‹ค์–‘ํ•œ ๋ฌธ์ œ์ ๊ณผ ํ•ด๊ฒฐ ๋ฐฉ์•ˆ์„ ์•Œ์•„๋ณด๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. ํŠธ๋žœ์žญ์…˜ ๋ฒ”์œ„์˜ ์˜์†์„ฑ ์ปจํ…์ŠคํŠธ ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ์˜ ๊ธฐ๋ณธ ์ „๋žต์€ 'ํŠธ๋žœ์žญ์…˜ ๋ฒ”์œ„์˜ ์˜์†์„ฑ ์ปจํ…์ŠคํŠธ' ์ž…๋‹ˆ๋‹ค. ์Šคํ”„๋ง์—์„œ JPA๋ฅผ ์‚ฌ์šฉํ•˜๊ฒŒ ๋˜๋ฉด, ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ๊ฐ€ ์ œ๊ณตํ•˜๋Š” ์ „๋žต์„ ๋”ฐ๋ผ์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ๋Š” JPA์˜ ์˜์†์„ฑ ์ปจํ…์ŠคํŠธ๋ฅผ ์ง€์›ํ•  ๋•Œ, ๊ธฐ๋ณธ ์ „๋žต์œผ๋กœ ํŠธ๋žœ์žญ์…˜ ๋ฒ”์œ„์˜ ์˜์†์„ฑ ์ปจํ…์ŠคํŠธ๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ํŠธ๋žœ์žญ์…˜..
JPA์—์„œ ์„ฑ๋Šฅ ์ตœ์ ํ™”๋ฅผ ํ•˜๊ธฐ ์œ„ํ•œ ๋ช‡๊ฐ€์ง€ ๋ฐฉ๋ฒ•๋“ค์„ ์•Œ์•„๋ณด๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. ๋ชจ๋“  ์—ฐ๊ด€๊ด€๊ณ„๋Š” ์ง€์—ฐ๋กœ๋”ฉ ๋ชจ๋“  ์—ฐ๊ด€๊ด€๊ณ„๋Š” FetchType.LAZY๋ฅผ ํ†ตํ•œ ์ง€์—ฐ๋กœ๋”ฉ์œผ๋กœ ์„ค์ •ํ•ด ์ฃผ์‹œ๋Š” ๊ฒƒ์„ ๊ถŒ์žฅํ•ฉ๋‹ˆ๋‹ค. ์ฆ‰์‹œ ๋กœ๋”ฉ์„ ์‚ฌ์šฉํ•  ๊ฒฝ์šฐ ์˜ˆ์ƒํ•˜์ง€ ๋ชปํ•œ ์ฟผ๋ฆฌ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ์ด๋Š” ์ตœ์ ํ™”๋ฅผ ๋ฐฉํ•ดํ•˜๋Š” ์š”์†Œ๊ฐ€ ๋ฉ๋‹ˆ๋‹ค. XToOne ๊ด€๊ณ„ ํŽ˜์น˜ ์กฐ์ธ์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ToOne ๊ด€๊ณ„๋ฅผ ๋ชจ๋‘ ์ง€์—ฐ ๋กœ๋”ฉ์œผ๋กœ ์„ค์ •ํ•œ ์ดํ›„, ์กฐํšŒํ•˜๋Š” ์‹œ์ ์— ํŽ˜์น˜ ์กฐ์ธ์„ ํ†ตํ•ด ์กฐํšŒํ•˜๋Š” ๊ฒƒ์œผ๋กœ ์„ฑ๋Šฅ์„ ํ–ฅ์ƒ์‹œํ‚ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ToOne ๊ด€๊ณ„๋Š” ์กฐํšŒ ์‹œ row์ˆ˜๋ฅผ ์ฆ๊ฐ€์‹œํ‚ค์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์—, ์•„๋ฌด๋Ÿฐ ๋ฌธ์ œ ์—†์ด ํŽ˜์ด์ง•๋„ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค. ์ฟผ๋ฆฌ๋ฅผ ์ž‘์„ฑํ•  ๋•Œ์—๋Š” ์—”ํ‹ฐํ‹ฐ๋กœ ์กฐํšŒํ•˜๋Š” ๋ฐฉ๋ฒ•๊ณผ, DTO๋กœ ๋ฐ”๋กœ ์กฐํšŒํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์„ ํƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์„ฑ๋Šฅ์„ ๊ทนํ•œ์œผ๋กœ ๋Œ์–ด์˜ฌ๋ฆฌ๋ ค๋Š” ๊ฒƒ์ด ..
๋ณ‘ํ•ฉ๊ณผ ๋ณ€๊ฒฝ๊ฐ์ง€ JPA๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ ์ผ๋ฐ˜์ ์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ๋ณ€๊ฒฝํ•˜๋Š” ๊ฒฝ์šฐ์—๋Š” ๋‘๊ฐ€์ง€ ๋ฐฉ๋ฒ•์ด ์กด์žฌํ•ฉ๋‹ˆ๋‹ค ํ•˜๋‚˜๋Š” ๋ณ€๊ฒฝ ๊ฐ์ง€(Dirty Checking)์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด๊ณ , ๋‹ค๋ฅธ ํ•˜๋‚˜๋Š” ๋ณ‘ํ•ฉ (merge())๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ธ๋ฐ, ๋ณ€๊ฒฝ ๊ฐ์ง€๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์„ ๊ถŒ์žฅํ•ฉ๋‹ˆ๋‹ค. ๋ณ‘ํ•ฉ(merge)์˜ ๋™์ž‘์›๋ฆฌ ๋ณ‘ํ•ฉ์„ ์‚ฌ์šฉํ•œ๋‹ค๋ฉด ์šฐ์„  ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๋„˜์–ด์˜จ ์ค€์˜์† ์—”ํ‹ฐํ‹ฐ์˜ ์‹๋ณ„์ž ๊ฐ’์œผ๋กœ 1์ฐจ ์บ์‹œ์—์„œ ์กฐํšŒํ•ฉ๋‹ˆ๋‹ค. ๋งŒ์•ฝ 1์ฐจ์บ์‹œ์— ์—”ํ‹ฐํ‹ฐ๊ฐ€ ์—†๋‹ค๋ฉด ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์—์„œ ์—”ํ‹ฐํ‹ฐ๋ฅผ ์กฐํšŒํ•œ ํ›„ 1์ฐจ ์บ์‹œ์— ์ €์žฅํ•ฉ๋‹ˆ๋‹ค. ์กฐํšŒํ•œ ์˜์† ์—”ํ‹ฐํ‹ฐ์— merge(์ƒˆ๋กœ์šด์—”ํ‹ฐํ‹ฐ) ์—์„œ ๋„ฃ์–ด์ค€ '์ƒˆ๋กœ์šด์—”ํ‹ฐํ‹ฐ'์˜ ๊ฐ’์„ ๋„ฃ์–ด์ค๋‹ˆ๋‹ค. ์ด๋•Œ ๋นˆ ๊ฐ’์€ ๋ฌด์‹œํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ null๋กœ ์ฑ„์›Œ๋„ฃ์Šต๋‹ˆ๋‹ค. ๋งŒ์•ฝ merge()์— ๋“ค์–ด๊ฐ„ ๊ฐ’๋“ค ์ค‘ null ๊ฐ’์ด ์žˆ๋‹ค๋ฉด ๊ทธ ๊ฐ’์ด ๋ฌด์‹œ๋˜๊ณ  ..
์Šคํ”„๋ง๋ถ€ํŠธ ์‚ฌ์šฉ ์‹œ EntityManagerFactory๋ฅผ ์ฃผ์ž…๋ฐ›๋Š” ๋ฐฉ๋ฒ• @PersistenceUnit ๋˜๋Š” ๊ทธ๋ƒฅ @Autowired๋ฅผ ์‚ฌ์šฉํ•ด๋„ ๋ฉ๋‹ˆ๋‹ค. ์‚ฌ์šฉ @PersistenceUnit private EntityManagerFactory emf; Reference ์‹ค์ „! ์Šคํ”„๋ง ๋ถ€ํŠธ์™€ JPA ํ™œ์šฉ1 - ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๊ฐœ๋ฐœ - ์ธํ”„๋Ÿฐ | ๊ฐ•์˜ ์‹ค๋ฌด์— ๊ฐ€๊นŒ์šด ์˜ˆ์ œ๋กœ, ์Šคํ”„๋ง ๋ถ€ํŠธ์™€ JPA๋ฅผ ํ™œ์šฉํ•ด์„œ ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์„ค๊ณ„ํ•˜๊ณ  ๊ฐœ๋ฐœํ•ฉ๋‹ˆ๋‹ค. ์ด ๊ณผ์ •์„ ํ†ตํ•ด ์Šคํ”„๋ง ๋ถ€ํŠธ์™€ JPA๋ฅผ ์‹ค๋ฌด์—์„œ ์–ด๋–ป๊ฒŒ ํ™œ์šฉํ•ด์•ผ ํ•˜๋Š”์ง€ ์ดํ•ดํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค., ์Šคํ”„ www.inflearn.com
์—”ํ‹ฐํ‹ฐ, ํ…Œ์ด๋ธ”, ์ปฌ๋Ÿผ๋ช… ์ƒ์„ฑ ์ „๋žต https://docs.spring.io/spring-boot/docs/2.1.3.RELEASE/reference/htmlsingle/#howtoconfigure-hibernate-naming-strategy https://docs.jboss.org/hibernate/orm/5.4/userguide/html_single/Hibernate_User_Guide.html#naming ์›๋ž˜ ํ•˜์ด๋ฒ„๋„ค์ดํŠธ๋Š” ์—”ํ‹ฐํ‹ฐ์˜ ํ•„๋“œ๋ช…์„ ๊ทธ๋Œ€๋กœ ํ…Œ์ด๋ธ”์˜ ์ปฌ๋Ÿผ๋ช…์œผ๋กœ ์‚ฌ์šฉํ–ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์Šคํ”„๋ง ๋ถ€ํŠธ๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค๋ฉด ์Šคํ”„๋ง ๋ถ€ํŠธ์˜ SpringPhysicalNamingStrategy๊ฐ€ ์ด๋ฆ„์„ ๋ฐ”๊ฟ”์ค๋‹ˆ๋‹ค. ์Šคํ”„๋ง ๋ถ€ํŠธ ๊ธฐ๋ณธ ์„ค์ • SpringPhysicalNamingStrategy๊ฐ€ ๊ธฐ๋ณธ์œผ๋กœ ๋ฐ”๊ฟ”์ฃผ๋Š” ์„ค..
๊ณ„์ธตํ˜• ๊ตฌ์กฐ ๋งคํ•‘ํ•˜๊ธฐ @Entity @Getter public class Category { @Id @GenerateValue @Column(name = "CATEGORY_ID") private Long id; private String name; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "PARENT_ID") private Category parent; @OneToMany(mappedBy = "parent") private List child = new ArrayList(); } ์ด๋ฆ„๋งŒ ์ž๊ธฐ ์ž์‹ ์ด์ง€, ๊ทธ๋ƒฅ ๋‹ค๋ฅธ ์—”ํ‹ฐํ‹ฐ์— ๋งคํ•‘ํ•˜๋Š” ๋А๋‚Œ์œผ๋กœ ๋งคํ•‘ํ•ด์ฃผ๋ฉด ๋ฉ๋‹ˆ๋‹ค. ์ƒ์„ฑ๋˜๋Š” ํ…Œ์ด๋ธ”์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค. Reference ์‹ค์ „! ์Šคํ”„๋ง ๋ถ€ํŠธ์™€ JPA ํ™œ์šฉ1 ..
ํŽ˜์น˜ ์กฐ์ธ(fetch join) ํŽ˜์น˜ ์กฐ์ธ์ด๋ž€ SQL ์กฐ์ธ์˜ ์ข…๋ฅ˜๊ฐ€ ์•„๋‹ˆ๋ฉฐ, JPQL์—์„œ ์„ฑ๋Šฅ ์ตœ์ ํ™”๋ฅผ ์œ„ํ•ด์„œ ์ œ๊ณตํ•ด์ฃผ๋Š” ๊ธฐ๋Šฅ์ž…๋‹ˆ๋‹ค. ํŽ˜์น˜ ์กฐ์ธ์€ ์—”ํ‹ฐํ‹ฐ๋ฅผ ์กฐํšŒํ•  ๋•Œ ์—ฐ๊ด€๋œ ์—”ํ‹ฐํ‹ฐ๋‚˜ ์ปฌ๋ ‰์…˜์„ ํ•œ๋ฒˆ์˜ SQL๋กœ ํ•จ๊ป˜ ์กฐํšŒํ•˜๋Š” ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•จ์œผ๋กœ์จ N+1๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋„์™€์ค๋‹ˆ๋‹ค. ์ผ๋ฐ˜ ์กฐ์ธ์€ ์‹คํ–‰ ์‹œ ์—ฐ๊ด€๋œ ์—”ํ‹ฐํ‹ฐ๋ฅผ ํ•จ๊ป˜ ์กฐํšŒํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋‹จ์ง€ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ƒ์—์„œ ํ…Œ์ด๋ธ”๊ฐ„์˜ ํƒ์ƒ‰์„ ์œ„ํ•ด ์‚ฌ์šฉ๋˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ธฐ์กด ์กฐ์ธ์˜ ๋ฌธ์ œ @Entity class Member( @Id @Column(name = "member_id") @GeneratedValue(strategy = GenerationType.IDENTITY) var id: Long = 0, var username: String, var age: In..
๋ฒŒํฌ ์—ฐ์‚ฐ ๋งŒ์•ฝ ํ•œ ํ•ด๊ฐ€ ์ง€๋‚˜์„œ ๋ชจ๋“  ํšŒ์›์˜ ๋‚˜์ด๋ฅผ 1์”ฉ ์˜ฌ๋ ค์ฃผ๋ ค๋ฉด ์–ด๋–ป๊ฒŒ ํ•ด์•ผํ• ๊นŒ์š”? JPA์˜ ๋ณ€๊ฒฝ ๊ฐ์ง€ ๊ธฐ๋Šฅ์œผ๋กœ ์‹คํ–‰ํ•˜๋ ค๋ฉด ๋„ˆ๋ฌด ๋งŽ์€ SQL์ด ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค. ์ด๋Ÿด ๋•Œ ๋ฒŒํฌ ์—ฐ์‚ฐ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š”๋ฐ, ์ฟผ๋ฆฌ ํ•œ๋ฒˆ์œผ๋กœ ์—ฌ๋Ÿฌ ํ…Œ์ด๋ธ”์˜ ๋กœ์šฐ๋ฅผ ๋ณ€๊ฒฝ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค. executeUpdate() ๋ฒŒํฌ ์—ฐ์‚ฐ์€ executeUpdate()๋ฅผ ํ†ตํ•ด ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ๋ฐ˜ํ™˜๊ฐ’์€ ์˜ํ–ฅ์„ ๋ฐ›์€ ์—”ํ‹ฐํ‹ฐ์˜ ์ˆ˜๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. UPDATE์™€ DELETE๋ฅผ ์ง€์›ํ•˜๋ฉฐ ํ•˜์ด๋ฒ„๋„ค์ดํŠธ์—์„œ๋Š” INSERT๋„ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค. em.createaQuery("delete from Product p where p.price < :price") .setParameter("price" , 100) .executeUpdate(); ๋ฒŒํฌ ์—ฐ์‚ฐ์˜ ์ฃผ์˜์  ๋ฒŒํฌ ์—ฐ์‚ฐ์€ ..
๋ง ๋ž‘
'๐Ÿ๏ธ Spring/JPA' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๊ธ€ ๋ชฉ๋ก (5 Page)