[TIL] JPA @OneToMany μ»¬λ ‰μ…˜ μˆ˜μ • μ‹œ 주의점 (μ»¬λ ‰μ…˜ 좔적)

2026. 3. 9. 21:41·Today I Learned 🧐/Project

 

 

 

 

 

JPA μ—”ν‹°ν‹°μ—μ„œ `@OneToMany` μ»¬λ ‰μ…˜μ„ μ—…λ°μ΄νŠΈν•  λ•Œ, 

리슀트λ₯Ό ν†΅μ§Έλ‘œ κ΅μ²΄ν•˜λ©΄ μ•ˆ λ˜λŠ” μ΄μœ μ— λŒ€ν•΄μ„œ 정리해 보렀고 ν•œλ‹€.

 

 

 

🚧 μˆ˜μ • μ „ μ½”λ“œ  - μ»¬λ ‰μ…˜μ„ μƒˆ 리슀트둜 ν• λ‹Ή

 

//Diary.kt

if (diaryActivityCategoryList.isNotEmpty()) {
    this.diaryActivityCategory?.clear()
    this.diaryActivityCategory = diaryActivityCategoryList
}

 

ν…ŒμŠ€νŠΈ κ³Όμ •μ—μ„œ λ³€κ²½ 감지(dirt checking)이 μ œλŒ€λ‘œ λ™μž‘ν•˜μ§€ μ•Šμ•„ 원인을 μ°Ύμ•„λ³΄μ•˜λ‹€.

 

 

πŸ“Œ JPA의 μ»¬λ ‰μ…˜ 좔적 

JPAλŠ” `@OneToMany`둜 λ§€ν•‘λœ μ»¬λ ‰μ…˜μ„ λ‘œλ”©ν•  λ•Œ, λ‹¨μˆœν•œ `ArrayList`κ°€ μ•„λ‹Œ Hibernate μ „μš© 래퍼 μ»¬λ ‰μ…˜ (`PersistentBag`, `PersistentList` λ“±)으둜 κ°μ‹Έμ„œ κ΄€λ¦¬ν•œλ‹€.

 

    @OneToMany(mappedBy = "diary", orphanRemoval = true, cascade = [CascadeType.ALL])
    var diaryActivityCategories: MutableList<DiaryActivityCategory> = mutableListOf()
        protected set

 

 

 

μ—”ν‹°ν‹°λ₯Ό μ‘°νšŒν•˜λ©΄ `diaryActivityCategories`μ—λŠ” μ‹€μ œλ‘œ `PersistentBag` νƒ€μž…μ΄ λ“€μ–΄κ°€ μžˆλ‹€.

이 `PersistentBag`이 λ‚΄λΆ€μ μœΌλ‘œ μ›λ³Έ μŠ€λƒ…μƒ·κ³Ό ν˜„μž¬ μƒνƒœλ₯Ό λΉ„κ΅ν•΄μ„œ μ–΄λ–€ μš”μ†Œκ°€ μΆ”κ°€/μ‚­μ œλ˜μ—ˆλŠ”μ§€ μΆ”μ ν•œλ‹€.

 

 

 

PersistentBag πŸŽ’

JPAκ°€ κ΄€λ¦¬ν•˜λŠ” μ»¬λ ‰μ…˜  GPS 좔적기가 달린 가방이라고 μƒκ°ν•˜λ©΄ μ΄ν•΄ν•˜κΈ° 쉽닀.

 

 

예λ₯Όλ“€μ–΄,

// 방법 1
this.diaryActivityCategory?.clear()
this.diaryActivityCategory?.addAll(diaryActivityCategoryList)

// 방법 2
this.diaryActivityCategory = diaryActivityCategoryList

 

 

방법 1은 JPAκ°€ μΆ”μ ν•˜λŠ” 가방은 κ·ΈλŒ€λ‘œ 두고 λ‚΄μš©λ¬Όλ§Œ λ°”κΏ”μ£ΌκΈ° λ•Œλ¬Έμ—, JPA μž…μž₯μ—μ„œ μ–΄λ–€ μš”μ†Œκ°€ μΆ”κ°€/μ‚­μ œ λ˜μ—ˆλŠ”μ§€ 좔적이 κ°€λŠ₯ν•˜λ‹€.

방법 2λŠ” JPAκ°€ μΆ”μ ν•˜λ˜ 가방을 버리고 μƒˆ κ°€λ°©μœΌλ‘œ κ΅μ²΄ν–ˆκΈ° λ•Œλ¬Έμ—, JPA μž…μž₯μ—μ„œ 더이상 좔적이 λΆˆκ°€λŠ₯ν•˜λ‹€.

 

 

 

πŸ‘·πŸ» μˆ˜μ • ν›„ μ½”λ“œ — 같은 μ»¬λ ‰μ…˜ μœ μ§€, λ‚΄μš©λ§Œ ꡐ체

if (diaryActivityCategoryList.isNotEmpty()) {
    this.diaryActivityCategory.clear()
    this.diaryActivityCategory.addAll(diaryActivityCategoryList)
}

 

JPAκ°€ μ²˜μŒλΆ€ν„° κ΄€λ¦¬ν•˜λ˜ μ»¬λ ‰μ…˜ κ°μ²΄λŠ” κ·ΈλŒ€λ‘œ 두고, μ•ˆμ˜ μš”μ†Œλ§Œ λΉ„μš°κ³ (`clear()`),  λ‹€μ‹œ μš”μ²­ 값을 μΆ”κ°€(`addAll()`)ν–ˆλ‹€.

 

 

 

μ°Έκ³  :

 

[JPA] πŸ’Ό PersistentBag

πŸ’Ό PersistentBagPersistentBag은 Hibernateμ—μ„œ μ œκ³΅ν•˜λŠ” μ»¬λ ‰μ…˜ νƒ€μž… 쀑 ν•˜λ‚˜λ‘œ, @OneToMany λ˜λŠ” @ManyToMany κ΄€κ³„μ—μ„œ μ‚¬μš©λ˜λŠ” List νƒ€μž…μ˜ μ»¬λ ‰μ…˜μ„ κ΄€λ¦¬ν•˜κΈ° μœ„ν•œ κ΅¬ν˜„μ²΄μ΄λ‹€. 이 μ»¬λ ‰μ…˜μ€ μ§€μ—° λ‘œλ”©(lazy lo

madeprogame.tistory.com

 

 

JPAμ—μ„œ μ»¬λ ‰μ…˜κ³Ό μ—¬λŸ¬ κΈ°λŠ₯ ν™œμš©ν•˜κΈ°

이전 κΈ€: https://gojs.tistory.com/57 μ˜μ†μ„± 관리 μ „λž΅νŠΈλžœμž­μ…˜ λ²”μœ„μ˜ μ˜μ†μ„± μ»¨ν…μŠ€νŠΈμŠ€ν”„λ§ μ»¨ν…Œμ΄λ„ˆλŠ” 기본적으둜 νŠΈλžœμž­μ…˜ λ²”μœ„μ˜ μ˜μ†μ„± μ»¨ν…μŠ€νŠΈ μ „λž΅μ„ κ°€μ§„λ‹€. νŠΈλžœμž­μ…˜μ΄ μ‹œμž‘λ˜λ©΄ μ˜μ†μ„±

gojs.tistory.com

 

 

μ €μž‘μžν‘œμ‹œ λΉ„μ˜λ¦¬ λ³€κ²½κΈˆμ§€ (μƒˆμ°½μ—΄λ¦Ό)

'Today I Learned 🧐 > Project' μΉ΄ν…Œκ³ λ¦¬μ˜ λ‹€λ₯Έ κΈ€

[TIL] Kotlin ν‘œν˜„μ‹ ν™œμš©ν•˜μ—¬ λ¦¬νŒ©ν† λ§ ν•˜κΈ°  (0) 2026.03.08
[TIL] JPA μ—”ν‹°ν‹° update 문제 ν•΄κ²° (JPA 더티체킹과 @Transactional)  (3) 2026.01.18
'Today I Learned 🧐/Project' μΉ΄ν…Œκ³ λ¦¬μ˜ λ‹€λ₯Έ κΈ€
  • [TIL] Kotlin ν‘œν˜„μ‹ ν™œμš©ν•˜μ—¬ λ¦¬νŒ©ν† λ§ ν•˜κΈ°
  • [TIL] JPA μ—”ν‹°ν‹° update 문제 ν•΄κ²° (JPA 더티체킹과 @Transactional)
ν•΄λ‹ˆ 🌳
ν•΄λ‹ˆ 🌳
🌱 + β˜€οΈ = 🌳
  • ν•΄λ‹ˆ 🌳
    haeni.dev
    ν•΄λ‹ˆ 🌳
  • 링크

    • github
    • velog
  • 전체
    였늘
    μ–΄μ œ
    • λΆ„λ₯˜ 전체보기 (15)
      • Dev Log ✏️ (6)
        • Tech (2)
        • μš°μ‚¬κΈ° κ°œλ°œμΌμ§€ 🐰 (4)
      • Today I Learned 🧐 (9)
        • Project (3)
        • Algorithm (0)
  • λΈ”λ‘œκ·Έ 메뉴

    • ν™ˆ
    • νƒœκ·Έ
    • λ°©λͺ…둝
  • 곡지사항

  • 인기 κΈ€

  • νƒœκ·Έ

    κ°œλ°œμΌμ§€
    springboot
    ci/cd
    til
    Java
    IT
    JPA
    kotlin
    μ•Œκ³ λ¦¬μ¦˜
    μ½”λ”©ν…ŒμŠ€νŠΈ
    AWS
    postgresql
    backend
    test
    μ½”ν…Œ
  • 졜근 λŒ“κΈ€

  • 졜근 κΈ€

  • hELLOΒ· Designed Byμ •μƒμš°.v4.10.5
ν•΄λ‹ˆ 🌳
[TIL] JPA @OneToMany μ»¬λ ‰μ…˜ μˆ˜μ • μ‹œ 주의점 (μ»¬λ ‰μ…˜ 좔적)
μƒλ‹¨μœΌλ‘œ

ν‹°μŠ€ν† λ¦¬νˆ΄λ°”