Spring Data JPA가 아닌 다른 이유로 인터페이스의 메서드를 직접 구현하고 싶을 때 사용하면 된다. 예를들어, JPA 직접 사용, 스프링 JDBC Template사용, MyBatis사용, Querydsl사용 등등이 있다.
사용자 정의 리포지토리 구현
먼저, 인터페이스를 만들어야 한다.
MemberRepositoryCustom Interface 생성
package study.datajpa.repository;
import study.datajpa.entity.Member;
import java.util.*;
public interface MemberRepositoryCustom {
List<Member> findMemberCustom();
}
그리고 인터페이스를 구현할 구현체 클래스를 만들어준다.
MemberRepositoryCustomImpl class 생성
package study.datajpa.repository;
import lombok.RequiredArgsConstructor;
import study.datajpa.entity.Member;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import java.util.List;
@RequiredArgsConstructor
public class MemberRepositoryCustomImpl implements MemberRepositoryCustom{
private final EntityManager em;
@Override
public List<Member> findMemberCustom() {
return em.createQuery("select m From Member m")
.getResultList();
}
}
그리고 Spring Data JPA 클래스에 인터페이스를 상속하면 된다.
MemberRepository 코드 추가 (인터페이스 상속)
public interface MemberRepository extends JpaRepository<Member, Long>, MemberRepositoryCustom {
...
}
이 기능은 Java에서 제공해주는 것이 아닌, Spring Data JPA에서 제공해주는 기능이다. 특히, 김영한님은 복잡해지는 쿼리들을 querydsl을 쓰기 위해 커스텀해서 사용한다고 한다.
해당 기능을 사용할 때 규칙이 있다.
- 규칙 : 리포지토리 인터페이스 이름 + Impl
- 규칙을 지켜야 Spring Data JPA가 인식해서 스프링 빈으로 등록한다고 한다.
- "리포지토리 인터페이스 이름" + "아무값" + "Impl" 적어도 인식하여 등록해주는 것 같다.
변경하는 방법도 있는데, 왜만하면 관례를 따르는게 유지보수성면에서 좋아보인다.
Auditing
엔티티 생성, 변경할 때 변경한 사람과 시간을 추적하고 싶을 때 사용
- 등록일
- 수정일
- 등록자
- 수정자
기본적으로 테이블을 만들 때, 등록일/수정일을 만들어야 운영에서 지옥을 맛보지 않는다고 한다. 추적이 되지 않기 때문이라고한다. 언제 등록이 됐고, 언제 수정이 됐는지는 기본으로 깔고가는 습관을 들여보자!
순수 JPA 사용
JpaBaseEntity 클래스 생성
package study.datajpa.entity;
import javax.persistence.Column;
import javax.persistence.MappedSuperclass;
import javax.persistence.PrePersist;
import javax.persistence.PreUpdate;
import java.time.LocalDateTime;
@MappedSuperclass
public class JpaBaseEntity {
@Column(updatable = false)
private LocalDateTime createdDate;
private LocalDateTime updatedDate;
@PrePersist // persist하기전에 event
public void prePersist() {
LocalDateTime now = LocalDateTime.now();
createdDate = now;
updatedDate = now;
}
@PreUpdate // update하기전에 event
public void preUpdate() {
updatedDate = LocalDateTime.now();
}
}
Member 엔티티에 상속
public class Member extends JpaBaseEntity {
...
}
Table 생성 쿼리
Spring Data JPA 사용
Main 클래스에 @EnableJpaAuditing, 등록자/수정자 메소드 추가
@EnableJpaAuditing
@SpringBootApplication
public class DataJpaApplication {
...
// 등록자, 수정자 값 가져오는 메소드
@Bean
public AuditorAware<String> auditorProvider() {
return () -> Optional.of(UUID.randomUUID().toString());
}
}
BaseEntity 클래스 생성
package study.datajpa.entity;
import lombok.Getter;
import org.springframework.data.annotation.CreatedBy;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedBy;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
import javax.persistence.Column;
import javax.persistence.EntityListeners;
import javax.persistence.MappedSuperclass;
import java.time.LocalDateTime;
@EntityListeners(AuditingEntityListener.class)
@MappedSuperclass
@Getter
public class BaseEntity {
// 등록일
@CreatedDate
@Column(updatable = false)
private LocalDateTime createdDate;
// 수정일
@LastModifiedDate
private LocalDateTime lastModifiedDate;
// 등록자
@CreatedBy
@Column(updatable = false)
private String createdBy;
// 수정자
@LastModifiedBy
private String lastModifiedBy;
}
Web 확장 - 페이징과 정렬
Web에서 페이징과 정렬을 하는 방법이다.
MemberController 메소드 추가
public class MemberController {
...
@GetMapping("/members")
public Page<Member> list(Pageable pageable){
Page<Member> page = memberRepository.findAll(pageable);
return page;
}
@PostConstruct
public void init() {
for(int i = 0; i < 100; i++){
memberRepository.save(new Member("user"+i, i));
}
}
}
파라미터에 Pageable을 추가하면 페이징과 sort기능을 사용할 수 있다. Page<Member>로 반환값을 하면 토탈값을 알 수 있다.
위처럼 url+"?page={페이지번호}&size={원하는사이즈}&sort={sort하고싶은 컬럼명},desc(기본 asc)"
을 사용하면 페이징과 정렬이 가능하다.
기본이 page별 사이즈가 20인데 apllication.yml, 파라미터로 수정할 수 있다.
application.yml
data:
web:
pageable:
default-page-size: 10
max-page-size: 2000
파라미터
@GetMapping("/members")
public Page<Member> list(@PageableDefault(size = 5) Pageable pageable){
Page<Member> page = memberRepository.findAll(pageable);
return page;
}
접두사
페이징 정보가 둘 이상이면 접두사로 구분한다.
- @Qualifier 에 접두사명 추가 "(접두사명)_xxx"
- 예) /members?member_page=0&order_page=1
public String list(
@Qualifier("member") Pageable memberPageable,
@Qualifier("order") Pageable orderPageable, ...
}
Dto 반환
@GetMapping("/members")
public Page<MemberDto> list(@PageableDefault(size = 5) Pageable pageable){
return memberRepository.findAll(pageable)
.map(member -> new MemberDto(member));
}
위와 같이 page에서 제공해주는 기능을 이용하면 된다.
출처
'spring > 인프런 강의 정리' 카테고리의 다른 글
[Querydsl] 2. 기본 문법 (0) | 2022.05.17 |
---|---|
[Querydsl] 1. 프로젝트 세팅 (0) | 2022.05.17 |
[Spring Data JPA] 3. 쿼리 메소드 기능 (0) | 2022.05.14 |
[Spring Data JPA] 2. 예제 도메인 모델과 동작확인 & 공통 인터페이스 (0) | 2022.05.13 |
[Spring Data JPA] 1. 스프링 데이터 JPA 시작 (0) | 2022.05.13 |