# [JPA] Spring Data JPA - ํ™•์žฅ ๊ธฐ๋Šฅ
Study Repository

[JPA] Spring Data JPA - ํ™•์žฅ ๊ธฐ๋Šฅ

by rlaehddnd0422

์ฟผ๋ฆฌ ๋ฉ”์†Œ๋“œ ๊ธฐ๋Šฅ์— ์ด์–ด ์ถ”๊ฐ€์ ์ธ ํ™•์žฅ ๊ธฐ๋Šฅ(์‚ฌ์šฉ์ž ์ •์˜ ๋ฆฌํฌ์ง€ํ† ๋ฆฌ ๊ตฌํ˜„, Auditing)์— ๋Œ€ํ•ด ์•Œ์•„๋ด…์‹œ๋‹ค.


์‚ฌ์šฉ์ž ์ •์˜ ๋ฆฌํฌ์ง€ํ† ๋ฆฌ ๊ตฌํ˜„

์Šคํ”„๋ง ๋ฐ์ดํ„ฐ JPA๋กœ ๋ฆฌํฌ์ง€ํ† ๋ฆฌ ๊ฐœ๋ฐœ ์‹œ ์ธํ„ฐํŽ˜์ด์Šค๋งŒ ์ •์˜ํ•˜๊ณ , ๊ตฌํ˜„์ฒด๋Š” ๋งŒ๋“ค์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

ํ•˜์ง€๋งŒ ์—ฌ๋Ÿฌ๊ฐ€์ง€ ์ด์œ ๋กœ ๋ฉ”์†Œ๋“œ๋ฅผ ์ง์ ‘ ๊ตฌํ˜„ํ•ด์•ผ ํ•  ๋•Œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

  • JPA ์ง์ ‘ ์‚ฌ์šฉ (EntityManager)
  • ์Šคํ”„๋ง JDBC Template ์‚ฌ์šฉ
  • MyBatis ์‚ฌ์šฉ 
  • ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ปค๋„ฅ์…˜ ์ง์ ‘์‚ฌ์šฉ
  • Querydsl ์‚ฌ์šฉ

๊ทธ๋ ‡๋‹ค๊ณ  ์ง์ ‘ ๋ฆฌํฌ์ง€ํ† ๋ฆฌ ๊ตฌํ˜„์ฒด๋ฅผ ๋งŒ๋“ค์ž๋‹ˆ ์ธํ„ฐํŽ˜์ด์Šค๊ฐ€ ์ œ๊ณตํ•˜๋Š” ๊ธฐ๋Šฅ๊นŒ์ง€ ๋ชจ๋‘ ๊ตฌํ˜„ํ•ด์•ผ ํ•˜๋Š”๋ฐ, ์ด๋Ÿฐ ๋ฌธ์ œ๋ฅผ ์šฐํšŒํ•ด์„œ ํ•„์š”ํ•œ ๋ฉ”์†Œ๋“œ๋งŒ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

 

1. ๊ตฌํ˜„ํ•˜๊ณ  ์‹ถ์€ ๋ฉ”์†Œ๋“œ๋ฅผ ์ธํ„ฐํŽ˜์ด์Šค ๋ ˆ๋ฒจ์— ์„ ์–ธ

public interface MemberRepositoryCustom {
    public List<Member> findMemberCustom(String name);
}

2. ๊ตฌํ˜„์ฒด์— ์„ ์–ธ ๋ฉ”์†Œ๋“œ Override

@RequiredArgsConstructor
public class MemberRepositoryCustomImpl implements MemberRepositoryCustom{

    private final EntityManager em;

    @Override
    public List<Member> findMemberCustom(String name) {
        return em.createQuery("select m from Member m where m.name like CONCAT('%',:name,'%')")
                .setParameter("name",name)
                .getResultList();
    }
}

 

๊ทœ์น™. ์ด ๋•Œ ๋ฐ˜๋“œ์‹œ ๊ตฌํ˜„์ฒด ์ด๋ฆ„์€ ์‚ฌ์šฉ์ž ์ง€์ • ์ธํ„ฐํŽ˜์ด์Šค ์ด๋ฆ„ + "Impl" ๋กœ ์ง€์ •ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

(์Šคํ”„๋ง ๋ฐ์ดํ„ฐ JPA Impl์„ ์ธ์‹ํ•ด์„œ ์Šคํ”„๋ง ๋นˆ์œผ๋กœ ๊ตฌํ˜„์ฒด๋ฅผ ๋“ฑ๋กํ•˜๊ธฐ ๋•Œ๋ฌธ์—)

 

3. Spring Data JPA ์ธํ„ฐํŽ˜์ด์Šค์— ์ถ”๊ฐ€๋กœ 1์—์„œ ์„ ์–ธํ•œ ์ธํ„ฐํŽ˜์ด์Šค ์ƒ์† 

public interface MemberRepository extends JpaRepository<Member, Long>, MemberRepositoryCustom{
	...
}

 

 

TestCode 

@Test
void customTest()
{
    memberRepository.save(new Member("KIM",10));
    memberRepository.save(new Member("KIM",15));
    List<Member> members = memberRepository.findMemberCustom("KIM");
    for (Member member : members) {
        System.out.println("member.getAge() = " + member.getAge());
    }
}

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์‚ฌ์šฉ์ž๊ฐ€ ์ง์ ‘ ๊ตฌํ˜„ํ•œ ์ฟผ๋ฆฌ๋ฅผ ํฌํ•จํ•œ ๋ฆฌํฌ์ง€ํ† ๋ฆฌ  + Spring Data JPA์„ ์‚ฌ์šฉํ•œ ๋ฆฌํฌ์ง€ํ† ๋ฆฌ๋ฅผ ํ•˜๋‚˜์˜ ์ ‘๊ทผ ๊ณ„์ธต์œผ๋กœ ๋งŒ๋“ค์–ด ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.


Auditing

์—”ํ‹ฐํ‹ฐ๋ฅผ ์ƒ์„ฑ, ๋ณ€๊ฒฝํ•  ๋•Œ ๋ณ€๊ฒฝํ•œ ์‚ฌ๋žŒ๊ณผ ์‹œ๊ฐ„์„ ์ถ”์ ํ•ด์ฃผ๋Š” ๊ธฐ๋Šฅ์ž…๋‹ˆ๋‹ค. 

+ ์ด ๊ธฐ๋Šฅ์€ ์ˆœ์ˆ˜ JPA๋ฅผ ์‚ฌ์šฉํ–ˆ์„ ๋•Œ๋„ ์ ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ˆœ์ˆ˜ JPA ์‚ฌ์šฉ

 

[JPA] ๊ณ ๊ธ‰ ๋งคํ•‘ : ๋งคํ•‘ ์ •๋ณด๋งŒ ์ œ๊ณตํ•˜๊ธฐ using @MappedSuperClass

์•ž์„œ ๋ฐฐ์šด ์ƒ์† ๊ด€๊ณ„๋งคํ•‘์€ ๋ถ€๋ชจ ํด๋ž˜์Šค์™€ ์ž์‹ ํด๋ž˜์Šค ๋ชจ๋‘ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ํ…Œ์ด๋ธ”๊ณผ ๋งคํ•‘ํ–ˆ์Šต๋‹ˆ๋‹ค. ๋งŒ์•ฝ ๋ถ€๋ชจ ํด๋ž˜์Šค๋Š” ํ…Œ์ด๋ธ”๊ณผ ๋งคํ•‘ํ•˜์ง€ ์•Š๊ณ  ๋ถ€๋ชจ ํด๋ž˜์Šค๋ฅผ ์ƒ์†๋ฐ›๋Š” ์ž์‹ ํด๋ž˜์Šค๋“ค์—๊ฒŒ ์ž

rlaehddnd0422.tistory.com

BaseEntity ์ •์˜ 

@MappedSuperclass
@Getter
public class JpaBaseEntity {
    @Column(updatable = false)
    private LocalDateTime createdDate;
    private LocalDateTime updatedDate;

    @PrePersist // persist ์ „ ์‹คํ–‰๋˜๋Š” ๋ฉ”์†Œ๋“œ
    public void prePersist() {
        LocalDateTime now = LocalDateTime.now();
        createdDate = now;
        updatedDate = now;
    }

    @PreUpdate // merge ์ „ ์‹คํ–‰๋˜๋Š” ๋ฉ”์†Œ๋“œ
    public void preUpdate() {
        updatedDate = LocalDateTime.now();
    }
}
  • JPA ์ฃผ์š” ์ด๋ฒคํŠธ ์–ด๋…ธํ…Œ์ด์…˜
    • @PrePersist,  @PostPersist : ์—”ํ‹ฐํ‹ฐ persist ์ „,ํ›„์— ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค.
    • @PreUpdate, @PostUpdate : ์—”ํ‹ฐํ‹ฐ ์—…๋ฐ์ดํ„ฐ ์ „, ํ›„์— ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค.
  • ์ด๋ฒคํŠธ ์–ด๋…ธํ…Œ์ด์…˜์„ ํ†ตํ•ด persist, update ์ „ createdDate, updatedDate๋ฅผ now() ๋กœ ์ดˆ๊ธฐํ™” ํ•ด์ค๋‹ˆ๋‹ค.

์ ์šฉ

public class Member extends JpaBaseEntity {

TestCode

@Test
@Transactional
@DisplayName("Base Entity ์ ์šฉ")
public void jpaBaseEntity() throws InterruptedException {
    //given
    Member member = new Member("member1");
    memberRepository.save(member); //@PrePersist

    Thread.sleep(100);

    em.flush(); //@PreUpdate
    em.clear();

    //when
    Member findMember = memberRepository.findById(member.getId()).get();
    //then
    System.out.println("findMember.createdDate = " + findMember.getCreatedDate());
    System.out.println("findMember.updatedDate = " + findMember.getUpdatedDate());
}

๊ฒฐ๊ณผ

findMember.createdDate = 2023-05-19T20:11:41.359666
findMember.updatedDate = 2023-05-19T20:11:41.498849

Spring Data JPA ์‚ฌ์šฉ

Spring Data JPA๋ฅผ ์‚ฌ์šฉํ•ด์„œ Auditing์„ ํ•˜๋ ค๋ฉด ์ถ”๊ฐ€์ ์ธ ์„ค์ •์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

 

์„ค์ •

  • @EnableJpaAuditing : ์Šคํ”„๋ง ๋ถ€ํŠธ ์„ค์ • ํด๋ž˜์Šค์— ์ ์šฉ
  • @EntityListeners(AuditingEntityListener.class) : Base ์—”ํ‹ฐํ‹ฐ์— ์ ์šฉ

๋“ฑ๋ก์ผ ๋ฐ ์ˆ˜์ •์ผ, ๋“ฑ๋ก์ž ๋ฐ ์ˆ˜์ •์ž BaseEntity

@EntityListeners(AuditingEntityListener.class)
@MappedSuperclass
public class BaseTimeEntity {

    @CreatedDate
    @Column(updatable = false)
    private LocalDateTime createdDate;

    @LastModifiedDate
    private LocalDateTime lastModified;
    
    @CreatedBy
    @Column(updatable = false)
    private String createdBy;
    
    @LastModifiedBy
    private String lastModifiedBy;
}
  • @CreatedDate : ๋“ฑ๋ก์ผ
  • @LastModifiedDate : ์ˆ˜์ •์ผ 
  • @CreatedBy : ๋“ฑ๋ก์ž 
  • @LastModifiedBy : ์ˆ˜์ •์ž

์Šคํ”„๋ง ๋ถ€ํŠธ ์„ค์ • ํด๋ž˜์Šค์— ๋นˆ ๋“ฑ๋ก ๋ฐ @EnableAuditing ์–ด๋…ธํ…Œ์ด์…˜ ์„ค์ •

@SpringBootApplication
@EnableJpaAuditing
public class DataJpaApplication {

   public static void main(String[] args) {
      SpringApplication.run(DataJpaApplication.class, args);
   }

   @Bean
   public AuditorAware<String> auditorProvider() {
      return () -> Optional.of(UUID.randomUUID().toString());
   }
}
 

๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ์ ์šฉํ•  ๋„๋ฉ”์ธ์— ์ƒ์†

public class Member extends BaseEntity {

์Šคํ”„๋ง ๋ฐ์ดํ„ฐ JPA๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์ˆœ์ˆ˜ JPA๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ ๋ณด๋‹ค ์ข€ ๋” ์œ ์—ฐํ•˜๊ฒŒ ์–ด๋…ธํ…Œ์ด์…˜์œผ๋กœ Auditing์„ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.


<์ฐธ๊ณ  ์ž๋ฃŒ>

 

๋ธ”๋กœ๊ทธ์˜ ์ •๋ณด

Study Repository

rlaehddnd0422

ํ™œ๋™ํ•˜๊ธฐ