사용자 정의 리포지토리 구현
- 필요한 기능을 따로 구현하는 경우에 사용한다.
- 실무에서는 주로 QueryDSL이나 SpringJdbcTemplate을 함께 사용할 때 사용함.
- 사용자 리포지토리가 항상 필요한 것은 아니다. 임의의 레포지토리를 만들어서 사용해도 됨.
방법
- 인터페이스에 작성
// interface 이름은 사용자가 임의로 지어도 무방
public interface MemberRepositoryCustom {
List<Member> findMemberCustom();
}
- 작성한 인터페이스를 구현하는 class 작성
- class는 이름 짓는 규칙이 정해져 있음.
@RequiredArgsConstructor
public class MemberRepositoryImpl implements MemberRepositoryCustom{
// interface는 이름을 임의로 설정해도 되지만, MemberRepositoryImple의 이름은 정해져 있음.
private final EntityManager em;
@Override
public List<Member> findMemberCustom() {
return em.createQuery("select m from Member m").getResultList();
}
}
- 기존의 repository에 사용자가 정한 인터페이스도 상속해줌.
public interface MemberRepository extends JpaRepository<Member,Long>,MemberRepositoryCustom {
- 사용
@Test
public void callCustom(){
List<Member> result = memberRepository.findMemberCustom();
}
Auditing
- 엔티티를 생성, 변경할 때 변경한 사람과 시간을 추적하고 싶으면?
- 등록일, 수정일, 등록자, 수정자
순수 JPA 기능으로 구현
- 공통 속성 정의
@Getter
@MappedSuperclass
public class JpaBaseEntity {
@Column(updatable = false) // 업데이트 불가능
private LocalDateTime createDate;
private LocalDateTime updateDate;
@PrePersist
public void prePersist(){
LocalDateTime now = LocalDateTime.now();
createDate = now;
updateDate = now;
}
@PreUpdate
public void preUpdate(){
updateDate = LocalDateTime.now();
}
}
- 상속
// Member Entity
@Entity
public class Member extends JpaBaseEntity{
- 테스트
@Test void jpaEventBaseEntity() throws Exception{
Member member = new Member("member1");
memberRepository.save(member); // @PrePersist 작동
Thread.sleep(100);
member.setUsername("member2");
entityManager.flush();
entityManager.clear();
Member findMember = memberRepository.findById(member.getId()).get();
System.out.println("findMember = " + findMember.getCreateDate());
System.out.println("findMember = " + findMember.getUpdateDate());
}
Data JPA로 구현
// @EnableJpaAuditing 어노테이션을 사용해줌.
@EnableJpaAuditing
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
@Bean // 등록, 업데이트를 한 사람이 잘 등록되는지 확인하기 위함.
public AuditorAware<String> auditorProvier(){
return () -> Optional.of(UUID.randomUUID().toString());
}
}
- 공통 속성Entity를 만들어준 뒤 @MaapedSuperclass 사용
- 순수 JPA와 다른 점은 application 클래스 위에 @EnableJpaAuditing 어노테이션과 BaseEntity에
@EntityListeners(AuditingEntityListener.class)를 사용. 속성에는 각자 역할에 맞는 어노테이션 사용해줌.
- 순수 JPA와 다른 점은 application 클래스 위에 @EnableJpaAuditing 어노테이션과 BaseEntity에
@Getter
@EntityListeners(AuditingEntityListener.class)
@MappedSuperclass
public class BaseEntity {
@CreatedDate
@Column(updatable = false)
private LocalDateTime createDate; // 시간
@LastModifiedDate
private LocalDateTime lastModifiedDate; // 시간
@CreatedBy
@Column(updatable = false)
private String createdBy; // 만든 사람
@LastModifiedBy
private String lasteModifiedBy; // 수정한 사람
}
- Entity에 상속
@Entity
public class Member extends BaseEntity{
- Test
@Test void jpaEventBaseEntity() throws Exception{
Member member = new Member("member1");
memberRepository.save(member); // @PrePersist 작동
Thread.sleep(100);
member.setUsername("member2");
entityManager.flush();
entityManager.clear();
Member findMember = memberRepository.findById(member.getId()).get();
System.out.println("findMember = " + findMember.getCreateDate());
System.out.println("findMember = " + findMember.getLastModifiedDate());
System.out.println("findMember = " + findMember.getCreatedBy());
System.out.println("findMember = " + findMember.getLasteModifiedBy());
}
- 결과
Web 확장 - 도메인 클래스 컨버터
- pk값을 @PathVariable로 받아오는 경우 Entity를 바로 조회가 가능하.ㅁ
- 조회용으로만 사용해야하고 사용을 권장하진 않음.
@GetMapping("/members2/{id}")
public String findMember2(@PathVariable("id") Member member){ // 조회용으로만 사용, 사용 권장하진 않음.
return member.getUsername();
}
Web 확장 - 페지이과 정렬
- 요청 파라미터
- 예) /members?page=0&size=5&sort=id,desc
- page: 현재 페이지 (0부터 시작)
- size: 한 페이지에 노출할 데이터 수
- sort: 정렬 조건을 정의 (asc는 생략 가능)
- 글로벌 설정은 yml에서 가능
spring:
data:
web:
pageable:
default-page-size: 10
max-page-size: 2000
// 어노테이션으로 값을 받앙올 수 있음. 이것 외에도 여러 설정 값들을 정해줄 수 있음.
@GetMapping("/members")
public Page<MemberDto> list(@PageableDefault(size=5) Pageable pageable){
Page<Member> page = memberRepository.findAll(pageable);
Page<MemberDto> map = page.map(MemberDto::new);
return map;
}
'JPA' 카테고리의 다른 글
[Querydsl] 중급 문법 (1) | 2024.02.20 |
---|---|
[Querydsl] 환경설정 및 기본 문법 (0) | 2024.02.05 |
[Data JPA] 벌크, @EntityGraph, Hint (1) | 2024.01.30 |
[Data JPA] 기본적인 사용법과 Dto 조회하기, 파라미터 바인딩 (1) | 2024.01.26 |
[JPA API] 컬렉션 조회 최적화 (0) | 2024.01.25 |