내일배움캠프

Spring μž…λ¬Έ 2μ£Όμ°¨ : JPA - 2

KIMHYEYUN 2023. 11. 7. 11:45
λ°˜μ‘ν˜•

JPA의 νŠΈλžœμž­μ…˜

νŠΈλžœμž­μ…˜μ΄λž€?

  • νŠΈλžœμž­μ…˜μ€ DB λ°μ΄ν„°λ“€μ˜ 무결성과 정합성을 μœ μ§€ν•˜κΈ° μœ„ν•œ ν•˜λ‚˜μ˜ 논리적 κ°œλ…
  • κ°€μž₯ 큰 νŠΉμ§•μ€ μ—¬λŸ¬ 개의 SQL이 ν•˜λ‚˜μ˜ νŠΈλžœμž­μ…˜μ— 포함될 수 있음
  • μ΄λ•Œ, λͺ¨λ“  SQL이 μ„±κ³΅μ μœΌλ‘œ μˆ˜ν–‰μ΄ 되면 DB에 영ꡬ적으둜 변경을 λ°˜μ˜ν•˜μ§€λ§Œ SQL 쀑 단 ν•˜λ‚˜λΌλ„ μ‹€νŒ¨ν•œλ‹€λ©΄ λͺ¨λ“  변경을 되돌림

  • μ˜μ†μ„± μ»¨ν…μŠ€νŠΈμ— Entity 객체듀을 μ €μž₯ν–ˆλ‹€κ³  ν•΄μ„œ DB에 λ°”λ‘œ λ°˜μ˜λ˜μ§€ μ•ŠμŒ

  • DBμ—μ„œ ν•˜λ‚˜μ˜ νŠΈλžœμž­μ…˜μ— μ—¬λŸ¬ 개의 SQL을 ν¬ν•¨ν•˜κ³  μžˆλ‹€κ°€ λ§ˆμ§€λ§‰μ— 영ꡬ적으둜 변경을 λ°˜μ˜ν•˜λŠ” 것 처럼 JPAμ—μ„œλ„ μ˜μ†μ„± μ»¨ν…μŠ€νŠΈλ‘œ κ΄€λ¦¬ν•˜κ³  μžˆλŠ” 변경이 λ°œμƒν•œ κ°μ²΄λ“€μ˜ 정보λ₯Ό μ“°κΈ° μ§€μ—° μ €μž₯μ†Œμ— μ „λΆ€ κ°€μ§€κ³  μžˆλ‹€κ°€ λ§ˆμ§€λ§‰μ— SQL을 ν•œλ²ˆμ— DB에 μš”μ²­μ— 변경을 λ°˜μ˜ν•¨

  • JPAμ—μ„œ μ΄λŸ¬ν•œ νŠΈλžœμž­μ…˜μ˜ κ°œλ…μ„ μ μš©ν•˜κΈ° μœ„ν•΄μ„œλŠ” EntityManagerμ—μ„œ EntityTransaction을 가져와 νŠΈλžœμž­μ…˜ 적용 κ°€λŠ₯

    • EntityTransaction et = em.getTransaction();
  • et.begin(); : νŠΈλžœμž­μ…˜ μ‹œμž‘

  • et.commit(); : νŠΈλžœμž­μ…˜μ˜ μž‘μ—…λ“€μ„ 영ꡬ적으둜 DB에 반영

  • et.rollback(); : 였λ₯˜κ°€ λ°œμƒν–ˆμ„ λ•Œ νŠΈλžœμž­μ…˜μ˜ μž‘μ—…μ„ λͺ¨λ‘ μ·¨μ†Œν•˜κ³ , 이전 μƒνƒœλ‘œ 되돌림

μ˜μ†μ„± μ»¨ν…μŠ€νŠΈμ˜ κΈ°λŠ₯

πŸ“Œ μ˜μ†μ„± μ»¨ν…μŠ€νŠΈλŠ” Entity 객체λ₯Ό 효율적으둜 μ‰½κ²Œ κ΄€λ¦¬ν•˜κΈ° μœ„ν•΄ λ§Œλ“€μ–΄μ§„ 곡간

1μ°¨ μΊμ‹œ

  • μ˜μ†μ„± μ»¨ν…μŠ€νŠΈλŠ” λ‚΄λΆ€μ μœΌλ‘œ μΊμ‹œ μ €μž₯μ†Œλ₯Ό κ°€μ§€κ³  있음
    • Entity 객체듀이 1μ°¨ μΊμ‹œ 즉, μΊμ‹œ μ €μž₯μ†Œμ— μ €μž₯됨
    • μΊμ‹œ μ €μž₯μ†ŒλŠ” Map 자료ꡬ쑰 ν˜•νƒœ
      • keyμ—λŠ” @Id둜 λ§€ν•‘ν•œ κΈ°λ³Έ ν‚€ 즉, μ‹λ³„μž 값을 μ €μž₯
      • valueμ—λŠ” ν•΄λ‹Ή Entity 클래슀의 객체λ₯Ό μ €μž₯
      • μ˜μ†μ„± μ»¨ν…μŠ€νŠΈλŠ” μΊμ‹œ μ €μž₯μ†Œμ— key에 μ €μž₯ν•œ μ‹λ³„μž 값을 μ‚¬μš©ν•˜μ—¬ Entity 객체λ₯Ό κ΅¬λΆ„ν•˜κ³  관리

Entity μ €μž₯

  • em.persist(memo); -> memo Entity 객체λ₯Ό μΊμ‹œ μ €μž₯μ†Œμ— μ €μž₯

Entity 쑰회

  1. μΊμ‹œ μ €μž₯μ†Œμ— μ‘°νšŒν•˜λŠ” Idκ°€ μ‘΄μž¬ν•˜μ§€ μ•ŠλŠ” 경우
    1. μΊμ‹œ μ €μž₯μ†Œ 쑰회
    2. DB SELECT 쑰회 ν›„ μΊμ‹œ μ €μž₯μ†Œμ— μ €μž₯
      • em.find(Memo.class, 1); 호좜 μ‹œ μΊμ‹œ μ €μž₯μ†Œμ— ν•΄λ‹Ή 값이 μ—†λ‹€λ©΄?
        -> DB에 SELECT 쑰회 ν›„ ν•΄λ‹Ή 값을 μΊμ‹œ μ €μž₯μ†Œμ— μ €μž₯ν•˜κ³  λ°˜ν™˜
  2. μΊμ‹œ μ €μž₯μ†Œμ— μ‘°νšŒν•˜λŠ” Idκ°€ μ‘΄μž¬ν•˜λŠ” 경우
  • em.find(Memo.class, 1); 호좜 μ‹œ μΊμ‹œ μ €μž₯μ†Œμ— μ‹λ³„μž 값이 1μ΄λ©΄μ„œ Memo Entity νƒ€μž…μΈ 값이 μžˆλŠ”μ§€ 쑰회 -> μžˆλ‹€λ©΄ λ°˜ν™˜

  • 1μ°¨ μΊμ‹œ μ‚¬μš© μž₯점

    1. DB 쑰회 횟수λ₯Ό μ€„μž„
    2. 1μ°¨ μΊμ‹œλ₯Ό μ‚¬μš©ν•΄ DB row 1개 λ‹Ή 객체 1κ°œκ°€ μ‚¬μš©λ˜λŠ” 것을 보μž₯(객체 동일성 보μž₯)

Entity μ‚­μ œ

  1. μ‚­μ œν•  Entityλ₯Ό μ‘°νšŒν•œ ν›„ μΊμ‹œ μ €μž₯μ†Œμ— μ—†λ‹€λ©΄ DB에 μ‘°νšŒν•΄μ„œ μ €
  2. em.remove(entity);
    • em.remove(memo); 호좜 μ‹œ μ‚­μ œν•  Entityλ₯Ό DELETED μƒνƒœλ‘œ λ§Œλ“  ν›„ νŠΈλžœμž­μ…˜ commit ν›„ DELETE SQL이 DB에 μš”μ²­λ¨

μ“°κΈ° μ§€μ—° μ €μž₯μ†Œ(ActionQueue)

  • JPAκ°€ νŠΈλžœμž­μ…˜μ²˜λŸΌ SQL을 λͺ¨μ•„μ„œ ν•œ λ²ˆμ— DB에 λ°˜μ˜ν•¨
    • JPAλŠ” 이λ₯Ό κ΅¬ν˜„ν•˜κΈ° μœ„ν•΄ μ“°κΈ° μ§€μ—° μ €μž₯μ†Œλ₯Ό λ§Œλ“€μ–΄ SQL을 λͺ¨μ•„두고 μžˆλ‹€κ°€ νŠΈλžœμž­μ…˜ commit ν›„ ν•œ λ²ˆμ— DB에 λ°˜μ˜ν•¨
  • flush()
    • νŠΈλžœμž­μ…˜ commit ν›„ μ“°κΈ° μ§€μ—° μ €μž₯μ†Œμ˜ SQL듀을 ν•œ λ²ˆμ— μš”μ²­λ¨
    • 사싀 commit ν›„ 좔가적인 λ™μž‘μ΄ μžˆλŠ”λ° 이것이 em.flush(); λ©”μ„œλ“œ 호좜
    • flush λ©”μ„œλ“œλŠ” μ˜μ†μ„± μ»¨ν…μŠ€νŠΈμ˜ λ³€κ²½ λ‚΄μš©λ“€μ„ DB에 λ°˜μ˜ν•˜λŠ” 역할을 μˆ˜ν–‰
      • 즉, μ“°κΈ° μ§€μ—° μ €μž₯μ†Œμ˜ SQL듀을 DB에 μš”μ²­ν•˜λŠ” 역할을 μˆ˜ν–‰

  • em.flush(); 호좜되자 λ°”λ‘œ DB에 μ“°κΈ° μ§€μ—° μ €μž₯μ†Œμ˜ SQL이 μš”μ²­
  • 이미 μ“°κΈ° μ§€μ—° μ €μž₯μ†Œμ˜ SQL이 μš”μ²­λ˜μ—ˆκΈ° λ•Œλ¬Έμ— 더 이상 μš”μ²­ν•  SQL이 μ—†μ–΄ νŠΈλžœμž­μ…˜μ΄ commit 된 후에 SQL 기둝이 μ—†μŒ

  • μΆ”κ°€) νŠΈλžœμž­μ…˜μ„ μ„€μ •ν•˜μ§€ μ•Šκ³  flush λ©”μ„œλ“œλ₯Ό ν˜ΈμΆœν•˜λ©΄ no transaction is in progress 메세지와 ν•¨κ»˜ TransactionRequiredException 였λ₯˜κ°€ λ°œμƒ
    • insert, update, delete 즉, 데이터 λ³€κ²½ SQL을 DB에 μš”μ²­ 및 λ°˜μ˜ν•˜κΈ° μœ„ν•΄μ„œλŠ” νŠΈλžœμž­μ…˜μ΄ ν•„μš”

      λ³€κ²½ 감지(Dirty Checking)

  • μ˜μ†μ„± μ»¨ν…μŠ€νŠΈμ— μ €μž₯된 Entityκ°€ 변경될 λ•Œλ§ˆλ‹€ Update SQL이 μ“°κΈ° μ§€μ—° μ €μž₯μ†Œμ— μ €μž₯λœλ‹€λ©΄??????
    • ν•˜λ‚˜μ˜ Update SQL둜 μ²˜λ¦¬ν•  수 μžˆλŠ” 상황을 μ—¬λŸ¬ 번 Update SQL을 μš”μ²­ν•˜κ²Œ 되기 λ•Œλ¬Έμ— λΉ„νš¨μœ¨μ 
  • κ·Έλ ‡λ‹€λ©΄ JPAλŠ” μ–΄λ–»κ²Œ Updateλ₯Ό 처리?
    • em.update(entity); 같은 λ©”μ„œλ“œλŠ” μ—†μŒ 😭

  • JPAλŠ” μ˜μ†μ„± μ»¨ν…μŠ€νŠΈμ— Entityλ₯Ό μ €μž₯ν•  λ•Œ 졜초 μƒνƒœ(LoadedState)λ₯Ό μ €μž₯
    • νŠΈλžœμž­μ…˜μ΄ commit되고 em.flush();κ°€ 호좜되면 Entity의 ν˜„μž¬ μƒνƒœμ™€ μ €μž₯ν•œ 졜초 μƒνƒœλ₯Ό 비ꡐ
    • λ³€κ²½ λ‚΄μš©μ΄ μžˆλ‹€λ©΄ Update SQL을 μƒμ„±ν•˜μ—¬ μ“°κΈ° μ§€μ—° μ €μž₯μ†Œμ— μ €μž₯ν•˜κ³  λͺ¨λ“  μ“°κΈ° μ§€μ—° μ €μž₯μ†Œμ˜ SQL을 DB에 μš”μ²­
    • λ§ˆμ§€λ§‰μœΌλ‘œ DB의 νŠΈλžœμž­μ…˜μ΄ commit λ˜λ©΄μ„œ 반영됨
  • λ”°λΌμ„œ λ³€κ²½ν•˜κ³  싢은 데이터가 μžˆλ‹€λ©΄ λ¨Όμ € 데이터λ₯Ό μ‘°νšŒν•˜κ³  ν•΄λ‹Ή Entity 객체의 데이터λ₯Ό λ³€κ²½ν•˜λ©΄ μžλ™μœΌλ‘œ Update SQL이 μƒμ„±λ˜κ³  DB에 반영됨
    • μ΄λŸ¬ν•œ 과정을 λ³€κ²½ 감지, Dirty Checking이라고 함
728x90
λ°˜μ‘ν˜•