CH05 Spring Data JPA

JpaRepository.save()

save() λŠ” λ‹¨μˆœνžˆ μ—”ν‹°ν‹°λ₯Ό μ €μž₯ν•΄μ£ΌλŠ” κΈ°λŠ₯을 μˆ˜ν–‰ν•˜λŠ” 것이 μ•„λ‹˜. κ²½μš°μ— 따라 persist λ˜λŠ” merge 둜 λ™μž‘ν•œλ‹€.

  • Transient μƒνƒœμ˜ 객체라면 EntityManager.persist()

  • Detached μƒνƒœμ˜ 객체라면 EntityManager.merge()

persist

Persist() λ©”μ†Œλ“œμ— νŒŒλΌλ―Έν„°λ‘œ λ„˜κΈ΄(save λŒ€μƒ) κ·Έ μ—”ν‹°ν‹° 객체λ₯Ό Persistent μƒνƒœλ‘œ λ³€κ²½ν•œλ‹€. save() 결과둜 λ°˜ν™˜λ°›μ€ saved entity κ°€ κ³§ νŒŒλΌλ―Έν„°λ‘œ λ„˜κΈ΄ κ·Έ save λŒ€μƒκ³Ό κ°™λ‹€.

@DataJpaTest
public class PostRepositoryTest {

    @Autowired
    PostRepository postRepository;

    @PersistenceContext
    EntityManager entityManager;

    @Test
    void saveTest() {
        Post post = new Post();
        post.setName("name_1");
        post.setDescription("description_1");
        Post savedPost = postRepository.save(post);

        Assertions.assertThat(entityManager.contains(post)).isTrue();
        Assertions.assertThat(entityManager.contains(savedPost)).isTrue();
        Assertions.assertThat(post).isEqualTo(savedPost);
    }

}

merge

주석 ν‘œμ‹œν•œ 것듀을 잘 κΈ°μ–΅ν•˜μž. update μ‹œ νŒŒλΌλ―Έν„°λ‘œ λ„˜κΈ΄ entityλŠ” μ˜μ†ν™”λ˜μ§€ μ•Šκ³  κ·Έκ²ƒμ˜ 볡사본이 μ˜μ†ν™” λœλ‹€. 그리고 μ˜μ†ν™”λœ 객체가 return λœλ‹€.

이 ν¬μΈνŠΈκ°€ μ£ΌλŠ” μ€‘μš”ν•œ μ‹œμ‚¬μ μ€ update 둜직 처리 이후 후속 μž‘μ—…μ„ ν•΄μ•Όν•  경우 λ°˜λ“œμ‹œ return 된 κ·Έ 값을 μ‚¬μš©ν•΄μ•Ό ν•œλ‹€λŠ” 것이닀. μ™œλƒν•˜λ©΄ κ·Έ 객체가 persistent 된 객체이기 λ•Œλ¬Έμ΄λ‹€. λ°˜λŒ€λ‘œ λ§ν•˜λ©΄ save() 의 νŒŒλΌλ―Έν„°λ‘œ λ„˜κΈ΄ 객체λ₯Ό μ‚¬μš©ν•΄μ„œλŠ” μ•ˆλœλ‹€λŠ” 것이닀.

μ™œ μ‚¬μš©ν•˜λ©΄ μ•ˆλ˜λƒ? managed 객체가 μ•„λ‹ˆκΈ° λ•Œλ¬Έμ΄λ‹€. 즉, persistent μƒνƒœκ°€ μ•„λ‹ˆκΈ° λ•Œλ¬Έμ— μƒνƒœκ°€ 좔적이 λ˜μ§€ μ•Šμ•„μ„œ dirty check λ“± JPA의 이점을 λˆ„λ¦¬μ§€ λͺ»ν•˜κΈ° λ•Œλ¬Έμ΄λ‹€.

entity의 일뢀 컬럼만 κ°€μ Έμ˜€λŠ” κΈ°λŠ₯인데 λ‚˜λŠ” μ‹€λ¬΄μ—μ„œ 써본적이 μ—†κ±°λ‹ˆμ™€ μ–»λŠ” μ„±λŠ₯ 효율 λŒ€λΉ„ μ½”λ“œ λ³΅μž‘λ„λ§Œ 더 μ»€μ§€λŠ” λŠλ‚Œμ΄λ‹€. 일단은 이런게 μžˆλ‹€ μ •λ„λ§Œ 인지해둔닀.

μ•„λž˜λŠ” κ°•μ˜ λ…ΈνŠΈ κ·ΈλŒ€λ‘œ 발췌.

  • μΈν„°νŽ˜μ΄μŠ€ 기반 ν”„λ‘œμ μ…˜

    • Nested ν”„λ‘œμ μ…˜ κ°€λŠ₯.

    • Closed ν”„λ‘œμ μ…˜

      • 쿼리λ₯Ό μ΅œμ ν™” ν•  수 μžˆλ‹€. κ°€μ Έμ˜€λ €λŠ” μ• νŠΈλ¦¬λ·°νŠΈκ°€ λ­”μ§€ μ•Œκ³  μžˆμœΌλ‹ˆκΉŒ.

      • Java 8의 λ””ν΄νŠΈ λ©”μ†Œλ“œλ₯Ό μ‚¬μš©ν•΄μ„œ 연산을 ν•  수 μžˆλ‹€.

    • Open ν”„λ‘œμ μ…˜

      • @Value(SpEL)을 μ‚¬μš©ν•΄μ„œ 연산을 ν•  수 μžˆλ‹€. μŠ€ν”„λ§ 빈의 λ©”μ†Œλ“œλ„ 호좜 κ°€λŠ₯. -쿼리 μ΅œμ ν™”λ₯Ό ν•  수 μ—†λ‹€. SpEL을 μ—”ν‹°ν‹° λŒ€μƒμœΌλ‘œ μ‚¬μš©ν•˜κΈ° λ•Œλ¬Έμ—.

  • 클래슀 기반 ν”„λ‘œμ μ…˜

    • DTO

    • 둬볡 @Value둜 μ½”λ“œ 쀄일 수 있음

Specification

query DSL κ³Ό μœ μ‚¬ν•˜κ²Œ query λ₯Ό ν”„λ‘œκ·Έλž¨μœΌλ‘œ μž‘μ„±ν•  수 μžˆλ„λ‘ ν•΄μ€€λ‹€. μ•„λž˜λŠ” JPA 곡식 λ¬Έμ„œμ—μ„œ Specificationarrow-up-right 에 λŒ€ν•΄ μ„€λͺ…ν•œ κΈ€ 일뢀닀.

JPA 2 introduces a criteria API that you can use to build queries programmatically. By writing a criteria, you define the where clause of a query for a domain class. Taking another step back, these criteria can be regarded as a predicate over the entity that is described by the JPA criteria API constraints.

μ‚¬μš© 방법은 κ³΅μ‹λ¬Έμ„œμ—λ„ λ‚˜μ™€μžˆμ§€λ§Œ κ°„λ‹¨ν•˜λ‹€. repository μ—μ„œ JpaSpecificationExecutor λ₯Ό 상속 λ°›κ³  findAll() 에 νŒŒλΌλ―Έν„°λ‘œ Specification 을 λ„˜κ²¨μ€€λ‹€. pageable 도 νŒŒλΌλ―Έν„°λ‘œ λ„˜κ²¨μ£Όλ©΄ νŽ˜μ΄μ§• μ²˜λ¦¬λ„ κ°€λŠ₯ν•˜λ‹€.

μœ μš©ν•˜μ§€λ§Œ νƒ€μž… μ„Έμ΄ν”„ν•˜μ§€ μ•Šμ•„μ„œ κ·Έλƒ₯ queryDsl μ“°λŠ”κ²Œ 마음 νŽΈν•˜λ‹€.

λ§Œμ•½ μ—¬κΈ°μ„œ μ•„λž˜μ™€ 같이 DESCRIPTION 에 null 을 넣을 경우 쿼리가 μ˜λ„ν•œλŒ€λ‘œ 달라진닀.

Auditing

νŠΉλ³„ν•œ λ‚΄μš©μ€ μ—†μ–΄μ„œ κ°•μ˜μžλ£Œλ§Œ μ²¨λΆ€ν•œλ‹€.

  • 메인 μ• ν”Œλ¦¬μΌ€μ΄μ…˜ μœ„μ— @EnableJpaAuditing μΆ”κ°€ (μŠ€ν”„λ§λΆ€νŠΈκ°€ μžλ™μ„€μ • ν•΄μ£Όμ§€ μ•ŠλŠ”λ‹€)

  • μ—”ν‹°ν‹° 클래슀 μœ„μ— @EntityListeners(AuditingEntityListener.class) μΆ”κ°€

Last updated