JPA

Java Persistence API λž€ ?

ORM 의 ν‘œμ€€ 기술둜 Hibernate, OpenJPA, EclipseLink, TopLink Essentials κ³Ό 같은 κ΅¬ν˜„μ²΄κ°€ 있고, μ΄λ“€μ˜ λŒ€ν•œ ν‘œμ€€ μΈν„°νŽ˜μ΄μŠ€ 이닀.

μž₯점

  • 객체지ν–₯적으둜 개발 및 데이터λ₯Ό 관리 ν•  수 있기 λ•Œλ¬Έμ— λΉ„μ§€λ‹ˆμŠ€ λ‘œμ§μ— 집쀑할 수 μžˆλ‹€.
  • ν…Œμ΄λΈ”μ˜ 생성, λ³€κ²½, 관리가 쉽닀.
  • λΉ λ₯Έ 개발이 κ°€λŠ₯ν•˜λ‹€.
  • DB 에 μ˜μ‘΄μ μ΄μ§€ μ•Šλ‹€.
    • MySQL, Oracle, Sysbase, Derby, PostgreSQL λ“±λ“±μ˜ 데이터 베이슀 지원
    • POJO 기반의 λͺ¨λΈμ˜ 지원

단점

  • 객체지ν–₯을 μ΄ν•΄ν•˜κ³  개발 ν•΄μ•Ό ν•˜λŠ” 만큼 λŸ¬λ‹μ»€λΈŒκ°€ λ†’λ‹€.
  • μ„±λŠ₯μƒμ˜ λ¬Έμ œκ°€ μžˆμ„μˆ˜ μžˆλ‹€.

참고자료

http://blog.woniper.net/255

μ˜μ†μ„±

Entity λ₯Ό 영ꡬ적으둜 μ €μž₯ν•΄μ£ΌλŠ” ν™˜κ²½μ„ μ˜λ―Έν•œλ‹€.

EntityManagerFactory 와 EntityManager

  • EntityManagerFactory
    • μƒμ„±ν•˜λŠ”λ° λΉ„μš©μ΄ 크닀.
    • μ–΄ν”Œλ¦¬μΌ€μ΄μ…˜ μ „μ²΄μ μœΌλ‘œ ν•œ 번만 μƒμ„±ν•˜μ—¬ κ³΅μœ ν•˜λ„λ‘ μ„€κ³„λ˜μ–΄ μžˆλ‹€.
    • μ—¬λŸ¬ μŠ€λ ˆλ“œμ—μ„œ λ™μ‹œμ— 접근해도 μ•ˆμ „ν•˜λ‹€.
    • μ„œλ‘œ λ‹€λ₯Έ μŠ€λ ˆλ“œμ˜ 곡유 κ°€λŠ₯
  • EntityManager
    • μƒμ„±ν•˜λŠ”λ° λΉ„μš©μ΄ μž‘λ‹€.
    • μ—¬λŸ¬ μŠ€λ ˆλ“œκ°€ λ™μ‹œμ— μ ‘κ·Όν•˜λ©΄ λ™μ‹œμ„± λ¬Έμ œκ°€ λ°œμƒν•œλ‹€.
    • μŠ€λ ˆλ“œκ°„μ˜ κ³΅μœ ν•˜μ§€ μ•ŠλŠ”λ‹€.

EntityManager λŠ” λ°μ΄ν„°λ² μ΄μŠ€μ˜ 연결이 κΌ­ ν•„μš”ν•œ μ‹œμ κΉŒμ§€λŠ” 컀λ„₯μ…˜μ„ 얻지 μ•ŠμŠ΅λ‹ˆλ‹€.
EntityManagerFactory 와 EntityManager λ₯Ό μƒμ„±ν•˜λŠ” μ½”λ“œλŠ” μ•„λž˜μ™€ κ°™μŠ΅λ‹ˆλ‹€.

EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("person"); // νŒŒλΌλ―Έν„° : μ˜μ†μ„± λ‹¨μœ„ 이름
EntityManager entityManager = entityManagerFactory.createEntityManager();

Persistance Context

μ˜μ†μ„± μ»¨ν…μŠ€νŠΈ (Persistance Context) λŠ” μ—”ν‹°ν‹°λ₯Ό 영ꡬ적으둜 μ €μž₯ν•˜λŠ” ν™˜κ²½ μ΄λΌλŠ” λœ»μ΄λ‹€.

EntityManager λ₯Ό μ΄μš©ν•˜μ—¬ Entityλ₯Ό μ €μž₯ν•˜κ±°λ‚˜ μ‘°νšŒν•  λ•Œ EntityManager λŠ” μ˜μ†μ„± μ»¨ν…μŠ€νŠΈμ— Entity λ₯Ό λ³΄κ΄€ν•˜κ³  κ΄€λ¦¬ν•œλ‹€.

[EntityManager 객체].persist([Entity 객체]) λ₯Ό μ‹€ν–‰ν•˜λ©΄ μ˜μ†μ„± μ»¨ν…μŠ€νŠΈκ°€ Entity λ₯Ό κ΄€λ¦¬ν•˜κ²Œ λœλ‹€.

Persistance Context λŠ” λˆˆμ— 보이지 μ•ŠλŠ” 논리적인 κ°œλ… 이닀.
λ˜ν•œ EntityManager λ₯Ό ν•˜λ‚˜ 생성할 λ•Œ ν•˜λ‚˜κ°€ λ§Œλ“€μ–΄μ§€λ©°, EntityManager λ₯Ό ν†΅ν•˜μ—¬ μ ‘κ·Όν•  수 있고 관리할 수 μžˆλ‹€.

Persistance Context 의 νŠΉμ§•μ€ μ•„λž˜μ™€ κ°™λ‹€.

  • μ˜μ†μ„± μ»¨ν…μŠ€νŠΈλŠ” Entity λ₯Ό μ‹λ³„μž κ°’μœΌλ‘œ κ΅¬λΆ„ν•©λ‹ˆλ‹€.

    • Entity μ—μ„œ @Id μ–΄λ…Έν…Œμ΄μ…˜μ„ ν†΅ν•˜μ—¬ μ§€μ •ν•œ 멀버 λ³€μˆ˜κ°€ μ˜μ†μ„± μ»¨ν…μŠ€νŠΈμ— μ‹λ³„μž κ°’μœΌλ‘œ μ €μž₯λœλ‹€.
  • JPA λŠ” 보톡 νŠΈλžœμž­μ…˜μ„ 컀밋 ν•˜λŠ” μˆœκ°„ μ˜μ†μ„± μ»¨ν…μŠ€νŠΈμ— μƒˆλ‘œ μ €μž₯된 Entity λ₯Ό λ°μ΄ν„°λ² μ΄μŠ€μ— λ°˜μ˜ν•œλ‹€.

    • μ΄λŸ¬ν•œ 과정을 flush 라고 ν•œλ‹€.
  • 1μ°¨ μΊμ‹œλ₯Ό μ‚¬μš©ν•œλ‹€.

    • μ˜μ†μ„± μ»¨ν…μŠ€νŠΈ 내뢀에 μ‘΄μž¬ν•˜λŠ” μΊμ‹œ (Map) 을 1μ°¨ μΊμ‹œλΌκ³  ν•œλ‹€.
    • μ˜μ† μƒνƒœμ˜ Entity λŠ” λͺ¨λ‘ 이곳에 μ €μž₯되며 ν‚€λŠ” @Id 둜 λ§€ν•‘ν•œ μ‹λ³„μžμ΄λ©° 값은 Entity μΈμŠ€ν„΄μŠ€μ΄λ‹€.
    • entityManager.find() λ©”μ„œλ“œλ₯Ό ν˜ΈμΆœν•˜λ©΄ λ¨Όμ € 1μ°¨ μΊμ‹œμ—μ„œ Entity λ₯Ό μ°Ύκ³ , λ§Œμ•½ μ°ΎλŠ” Entity κ°€ 1μ°¨ μΊμ‹œμ— μ—†μœΌλ©΄ λ°μ΄ν„°λ² μ΄μŠ€μ—μ„œ μ‘°νšŒν•œ ν›„ 1μ°¨ μΊμ‹œμ— μ €μž₯ν•˜κ³  μ˜μ† μƒνƒœμΈ ν•΄λ‹Ή 객체λ₯Ό λ°˜ν™˜ν•œλ‹€.
  • 객체의 동일성을 보μž₯ν•œλ‹€.

    • 1μ°¨ μΊμ‹œμ— μžˆλŠ” 같은 Entity λ₯Ό λ°˜ν™˜ν•˜κΈ° λ•Œλ¬Έμ— Entity 의 동일성을 보μž₯ν•œλ‹€.
  • νŠΈλžœμž­μ…˜μ„ μ§€μ›ν•˜λŠ” μ“°κΈ° 지연을 μˆ˜ν–‰ν•œλ‹€.

    • EntityManager λŠ” νŠΈλžœμž­μ…˜μ„ 컀밋 ν•˜κΈ° μ§μ „κΉŒμ§€ λ°μ΄ν„°λ² μ΄μŠ€μ— Entityλ₯Ό μ €μž₯ν•˜μ§€ μ•Šκ³  μ˜μ†μ„± μ»¨ν…μŠ€νŠΈμ˜ λ‚΄λΆ€ SQL μ €μž₯μ†Œμ— 생성 쿼리λ₯Ό μ €μž₯ν•΄ λ‘”λ‹€.
    • 이후 컀밋을 ν•˜κ²Œ 되면 μ €μž₯ν•΄λ‘μ—ˆλ˜ 쿼리λ₯Ό λ°μ΄ν„°λ² μ΄μŠ€μ— λ³΄λƒ…λ‹ˆλ‹€.
  • 변경을 κ°μ§€ν•œλ‹€.

    • μ˜μ†μ„± μ»¨ν…μŠ€νŠΈμ—λŠ” 이전 flush() λ•Œμ˜ Entity μƒνƒœλ₯Ό λ³΅μ‚¬ν•΄μ„œ μ €μž₯ν•΄λ‘” μŠ€λƒ…μƒ·μ΄ μ‘΄μž¬ν•œλ‹€.
    • JPA λŠ” flush() μ‹œμ μ— μŠ€λƒ…μƒ·κ³Ό Entity λ₯Ό 비ꡐ해 λ³€κ²½λœ Entity λ₯Ό μ°ΎλŠ”λ‹€.
    • λ§Œμ•½ λ³€κ²½λœ Entity κ°€ μžˆλ‹€λ©΄ 각각의 객체에 λŒ€ν•œ μˆ˜μ • 쿼리λ₯Ό λ§Œλ“€μ–΄ μ“°κΈ° 지연 SQL μ €μž₯μ†Œμ— μ €μž₯ν•œ ν›„ ν•œκΊΌλ²ˆμ— λ°μ΄ν„°λ² μ΄μŠ€λ‘œ 보내 νŠΈλžœμž­μ…˜μ„ μ»€λ°‹ν•œλ‹€.
    • λ³€κ²½ κ°μ§€λŠ” μ˜μ†μ„± μ»¨ν…μŠ€νŠΈκ°€ κ΄€λ¦¬ν•˜λŠ” μ˜μ† μƒνƒœμ˜ μ—”ν‹°ν‹°μ—λ§Œ 적용되며, μ€€μ˜μ† μƒνƒœμ˜ κ°μ²΄λŠ” κ°μ§€ν•˜μ§€ λͺ»ν•œλ‹€.
  • 지연 λ‘œλ”©μ„ μˆ˜ν–‰ν•œλ‹€.

    • μ‹€μ œ 객체 λŒ€μ‹  ν”„λ‘μ‹œ 객체λ₯Ό λ‘œλ”©ν•΄λ‘κ³  ν•΄λ‹Ή 객체λ₯Ό μ‹€μ œ μ‚¬μš©ν•  λ•Œ μ˜μ†μ„± μ»¨ν…μŠ€νŠΈλ₯Ό 톡해 데이터λ₯Ό λΆˆλŸ¬μ˜€λŠ” 방법이닀.

Life Cycle

Entity 생λͺ…μ£ΌκΈ°

Entity λŠ” μœ„μ™€ 같이 4가지 μƒνƒœκ°€ μ‘΄μž¬ν•œλ‹€.

  • λΉ„μ˜μ† (new)

μ˜μ†μ„± μ»¨ν…μŠ€νŠΈμ™€ μ „ν˜€ 관계가 μ—†λŠ” μƒνƒœ

객체 생성

Person kim = new Person("Kim");
  • μ˜μ† (managed)

μ˜μ†μ„± μ»¨ν…μŠ€νŠΈμ— μ €μž₯된 μƒνƒœ

객체 생성 ν›„ EntityManager λ₯Ό ν†΅ν•˜μ—¬ μ˜μ†μ„± μ»¨ν…μŠ€νŠΈμ— μ €μž₯

entityManager.persist(kim);
  • μ€€μ˜μ† (detached)

μ˜μ†μ„± μ»¨ν…μŠ€νŠΈμ— μ €μž₯λ˜μ—ˆλ‹€κ°€ λΆ„λ¦¬λœ μƒνƒœ

μ˜μ†μ„± μ»¨ν…μŠ€νŠΈκ°€ μ˜μ† μƒνƒœμ˜€λ˜ Entity λ₯Ό κ΄€λ¦¬ν•˜μ§€ μ•ŠμŒ (3가지 방법)

entityManager.detach(kim);
entityManager.closed(); // μ˜μ†μ„± μ»¨ν…μŠ€νŠΈ μ’…λ£Œ
entityManager.clear(); // μ˜μ†μ„± μ»¨ν…μŠ€νŠΈ μ΄ˆκΈ°ν™”

μ€€μ˜μ† μƒνƒœκ°€ 되면 1μ°¨ μΊμ‹œλΆ€ν„° 쓰기지연 SQL μ €μž₯μ†ŒκΉŒμ§€ ν•΄λ‹Ή μ—”ν‹°ν‹°λ₯Ό κ΄€λ¦¬ν•˜κΈ° μœ„ν•œ λͺ¨λ“  정보가 제거됨

μ˜μ†μ„± μ»¨ν…μŠ€νŠΈκ°€ μ œκ³΅ν•˜μ˜€λ˜ μ–΄λ– ν•œ κΈ°λŠ₯λ“€ (1μ°¨ μΊμ‹œ) 등을 μ œκ³΅ν•˜μ§€ μ•ŠλŠ”λ‹€.
이미 ν•œλ²ˆ μ˜μ† μƒνƒœμ˜€κΈ° λ•Œλ¬Έμ— λ°˜λ“œμ‹œ μ‹λ³„μž 값을 가지고 μžˆλ‹€. 지연 λ‘œλ”© μ‹œ λ¬Έμ œκ°€ λ°œμƒν•œλ‹€.

  • μ‚­μ œ (removed)

μ‚­μ œλœ μƒνƒœ

μ˜μ†μ„± μ»¨ν…μŠ€νŠΈμ™€ λ°μ΄ν„°λ² μ΄μ„œμ˜ Entity μ‚­μ œ

entityManager.remove(kim);

μ€€μ˜μ† -> μ˜μ† (merge)

μ€€μ˜μ† μƒνƒœλ₯Ό μ˜μ† μƒνƒœλ‘œ λ³€κ²½ν•˜λ €λ©΄ 병합 (merge) 과정을 거쳐야 ν•œλ‹€.

Person kim = new Person(1, "kim");
entityManager.persist(kim);
entityManager.detech(kim);
kim.setUserName("myungseok");
Person mergedKim = entityManager.merge(kim);
kim.getUserName();  // kim
mergedKim.getUserName();  // myungseok
entityManager.contains(kim);  // false
entityManager.contains(mergedKim);  // true

μœ„μ™€ 같이 merge() λ©”μ„œλ“œλ₯Ό μˆ˜ν–‰ν•˜λ©΄ 이전 Entity 인 kim 이 μ˜μ† μƒνƒœλ‘œ λ³€ν•˜λŠ”κ²Œ μ•„λ‹ˆλΌ μƒˆλ‘œμš΄ μ˜μ† μƒνƒœμ˜ Entity λ₯Ό λ°˜ν™˜ν•œλ‹€.
λ”°λΌμ„œ kim κ³Ό mergedKim 은 μ„œλ‘œ 같은 객체가 μ•„λ‹ˆλ‹€.

kim κ°μ²΄λŠ” merge() 후에도 μ€€μ˜μ† μƒνƒœλ‘œ λ‚¨μ•„μžˆκ²Œ λœλ‹€.

flush()

flush() λŠ” μ•„λž˜μ˜ 과정에 따라 μ˜μ†μ„± μ»¨ν…μŠ€νŠΈμ˜ 변경사항을 데이터 λ² μ΄μŠ€μ— λ°˜μ˜ν•œλ‹€.

  1. 변경감지가 λ™μž‘ν•˜μ—¬ μ˜μ†μ„± μ»¨ν…μŠ€νŠΈμ— μžˆλŠ” λͺ¨λ“  Entity λ₯Ό μŠ€λƒ…μƒ·κ³Ό λΉ„κ΅ν•œ ν›„ μˆ˜μ •λœ Entity λ₯Ό μ°ΎλŠ”λ‹€.
  2. μˆ˜μ •λœ Entity λŠ” μˆ˜μ • 쿼리λ₯Ό λ§Œλ“€μ–΄ μ“°κΈ° 지연 SQL μ €μž₯μ†Œμ— μ €μž₯ν•œλ‹€. (등둝, μˆ˜μ •, μ‚­μ œ)
  3. μ“°κΈ° 지연 SQL μ €μž₯μ†Œμ˜ 쿼리λ₯Ό λ°μ΄ν„°λ² μ΄μŠ€μ— 전솑

flush() 을 ν˜ΈμΆœν•˜λŠ” 방법은 μ•„λž˜ 3가지 이닀.

  • μ§μ ‘ν˜ΈμΆœ
    • EntityManager 의 flush() λ₯Ό 직접 ν˜ΈμΆœν•΄ κ°•μ œλ‘œ flush() ν•˜λŠ” 방법이닀.
    • 거의 μ‚¬μš©ν•˜μ§€ μ•ŠλŠ”λ‹€.
  • νŠΈλžœμž­μ…˜ μ»€λ°‹μ‹œ ν”ŒλŸ¬μ‹œ μžλ™ 호좜
    • JPA λŠ” νŠΈλžœμž­μ…˜μ„ 컀밋할 λ•Œ μžλ™μœΌλ‘œ flush() 을 ν˜ΈμΆœν•œλ‹€.
  • JPQL 쿼리 μ‹€ν–‰ μ‹œ flush() μžλ™ 호좜
    • JPQL 같은 객체지ν–₯ 쿼리λ₯Ό ν˜ΈμΆœν•  λ•Œλ„ 쿼리 μ‹€ν–‰ 직전에 flush() κ°€ μžλ™μœΌλ‘œ ν˜ΈμΆœλœλ‹€.