1. 사용자 정의 Repository 구현
[사용자 정의 인터페이스]
public interface MemberRepositoryCustom {
List<Member> findMemberCustom();
}
[구현 클래스]
- 규칙 : 사용자 정의 인터페이스 이름 + "Impl"
@RequiredArgsConstructor
public class MemberRepositoryCustomImpl implements MemberRepositoryCustom {
private final EntityManager em;
@Override
public List<Member> findMemberCustom() {
return em.createQuery("select m from Member m").getResultList();
}
}
[사용자 정의 인터페이스 상속]
public interface MemberRepository extends JpaRepository<Member, Long>, MemberRepositoryCustom {
}
[사용자 정의 메서드 호출]
List<Member> result = memberRepository.findMemberCustom();
2. Auditing
→ 엔티티 객체의 생성, 변경할 때의 변경한 사람과 시간을 추적하고 싶을 때
[순수 JPA]
어노테이션
→ @PrePersist, @PreUpdate
@MappedSuperclass // 속성들을 사용할 수 있게끔 한다.
@Getter
public class JpaBaseEntity {
@Column(updatable = false)
private LocalDateTime createdDate;
private LocalDateTime updatedDate;
@PrePersist
public void prePersist() {
LocalDateTime now = LocalDateTime.now();
createdDate = now;
updatedDate = now; // Null 시 Null 처리가 번거로워짐
}
@PreUpdate
public void preUpdate() {
updatedDate = LocalDateTime.now();
}
}
public class Member extends JpaBaseEntity {
}
[스프링 데이터 JPA]
어노테이션
→ @CreatedDate, @LastModifiedDate, @CreatedBy, @LastModifiedBy
1) 등록자 / 수정자를 처리해주는 AuditorAware 스프링 빈으로 등록
→ 실무에서는 세션 정보나, 스프링 시큐리티 로그인 정보 ID를 받아온다.
@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());
}
}
2) 등록시간 / 수정시간 추적
@MappedSuperclass
@Getter
@EntityListeners(AuditingEntityListener.class) // 엔티티에 적용
public class BaseEntity {
@CreatedDate
@Column(updatable = false)
private LocalDateTime createdDate;
@LastModifiedDate
private LocalDateTime lastModifiedDate;
}
3) 등록시간 / 수정시간 + 등록자 / 수정자 추적
@MappedSuperclass
@Getter
public class BaseTimeEntity extends BaseEntity {
@CreatedBy
@Column(updatable = false)
private String createdBy;
@LastModifiedBy
private String lastModifiedBy;
}
4) 관련 정보를 추적할 엔티티에서 상속
public class Member extends BaseEntity {
}
public class Member extends BaseTimeEntity {
}
3. 도메인 클래스 컨버터
→ HTTP 파라미터로 넘어온 엔티티 id로, 엔티티 객체를 찾아서 바인딩
cf. 도메인 클래스 컨버터로 받은 엔티티는, 트랜잭션이 없는 범위에서 엔티티를 조회했으므로 엔티티를 변경해도 DB에 반영되지 않는다.
@RestController
@RequiredArgsConstructor
public class MemberController {
private final MemberRepository memberRepository;
// 도메인 클래스 컨버터 사용 전
@GetMapping("/members/{id}")
public String findMember(@PathVariable("id") Long id) {
Member member = memberRepository.findById(id);
return member.getUsername();
}
// 도메인 클래스 컨버터 사용 후
@GetMapping("/members/{id}")
public String findMember2(@PathVariable("id") Member member) {
return member.getUsername();
}
}
4. 페이징과 정렬
url 파라미터로 Pageable을 받을 수 있다.
이 때 Pageable은 인터페이스, 실제 구현체로는 PageRequest 객체를 생성해 주입한다.
[요청 파라미터]
- ex. /members?page=0&size=5&sort=age,desc
- page : 현재 페이지, 0 시작
- size : 한 페이지에 노출할 데이터 수
- sort : 정렬 조건
[페이지 사이즈 설정]
spring:
data:
web:
pageable:
default-page-size: 20
max-page-size: 1000
[페이징 조건 여러 개]
- 페이징 정보가 여러 개이면 접두사로 구분
- ex. /members?member_page=0&order_page=0
@GetMapping("/members")
public String list(@Qualifier("member") Pageable memberPageable,
@Qualifier("order") Pageable orderPageable) {
memberRepository.ex(memberPageable, orderPageable);
}
[예시 코드]
@GetMapping("/members")
public Page<MemberDto> list(@PageableDefault(page = 0, size = 5, sort = "age") Pageable pageable) {
Page<Member> page = memberRepository.findAll(pageable);
return page.map(member -> new MemberDto(member.getId(), member.getUsername(), null));
}
'Spring > Spring Data Jpa' 카테고리의 다른 글
7. Projections (0) | 2024.04.13 |
---|---|
6. 스프링 데이터 JPA 분석 (0) | 2024.04.12 |
4. 쿼리 메소드 기능 (0) | 2024.03.25 |
3. 공통 인터페이스 기능 (1) | 2024.03.24 |
2. 예제 도메인 모델 (1) | 2024.03.23 |