[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 ์ฌ์ฉ
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์ ์ฒ๋ฆฌํ ์ ์์ต๋๋ค.
<์ฐธ๊ณ ์๋ฃ>
'๐ Backend > Spring Data JPA' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[JPA] Spring Data JPA ๊ตฌํ์ฒด(SimpleJpaRepository) ๋ถ์ (0) | 2023.05.22 |
---|---|
[JPA] Spring Data JPA - Web ํ์ฅ ๊ธฐ๋ฅ (0) | 2023.05.22 |
[JPA] Spring Data JPA - ์ฟผ๋ฆฌ ๋ฉ์๋ ๊ธฐ๋ฅ (0) | 2023.05.18 |
[JPA] JPQL ๋ฌธ๋ฒ 4 - ๋คํ์ฑ ์ฟผ๋ฆฌ, ์ํฐํฐ ์ง์ ์ฌ์ฉ, Named ์ฟผ๋ฆฌ (0) | 2023.05.10 |
[JPA] JPQL ๋ฌธ๋ฒ 3 - ๊ฒฝ๋ก ํํ์, ์๋ธ ์ฟผ๋ฆฌ, ์กฐ๊ฑด์ (0) | 2023.05.10 |
๋ธ๋ก๊ทธ์ ์ ๋ณด
Study Repository
rlaehddnd0422