✔️ 사용자 정의 리포지토리 구현
스프링 데이터 JPA 외에
JPA 직접사용
JDBC Template
Querydsl 사용
데이터베이스 커넥션 직접 사용 등 ..
인터페이스 메서드를 직접 구현하고 싶을 때 사용
// 사용자 정의 인터페이스
public interface MemberRepositoryCustom {
List<Member> findMemberCustom();
}
사용자 정의 인터페이스 구현 클래스
@RequiredArgsConstructor
public class memberRepositoryImpl 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 {
}
✔️ 사용자 정의 구현 클래스
- 규칙 : 리포지토리 인터퍼이스 이름 || 사용자 정의 인터페이스 이름 + Impl
- 스프링 데이터 JPA가 인식해서 스프링 빈으로 등록
Impl 대신 다른 이름 사용시
// XML
<repositories base-package="study.datajpa.repository"
repository-impl-postfix="Impl" />
// JavaConfig 설정
@EnableJpaRepositories(basePackages = "study.datajpa.repository", repositoryImplementationPostfix = "Impl")
여기서는
리포지토리의 이름 : MemberRepository,
사용자 정의 인터페이스의 이름 : MemberRepositoryCustom
✔️ Auditing
엔티티를 생성, 변경 시 변경한 사람과 시간을 추적하고 싶다면?
- 등록일
- 수정일
- 등록자
- 수정자
순수 JPA
@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;
}
@PreUpdate
public void preUpdate() {
updatedDate = LocalDateTime.now();
}
}
JPA 주요 이벤트 어노테이션
// em.flush() 호출될때 prePersist, preUpdate가 호출
@PrePersist // 영속화 전 콜백 메서드
@PostPersist // 영속화 후 콜백 메서드
@PreUpdate // DB에 Entity 업데이트 전 콜백 메서드
@PostUpdate // DB에 Entity 업데이트 후 콜백 메서드
스프링 데이터 JPA
- @EnableJpaAuditing : 스프링 부트 설정 클래스에 적용
- @EntityListeners(AuditingEntityListener.class) : 엔티티 적용
Config 클래스
@EnableJpaAuditing // Auditing 적용
@SpringBootApplication
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());
}
// 여기서는 UUID 로 하였지만 사용자가 누군지 식별할 수 있는 값으로 하면 됨
}
// 등록, 수정일
@Getter
@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
public class BaseTimeEntity {
@CreatedDate
@Column(updatable = false)
private LocalDateTime createdDate;
@LastModifiedDate
private LocalDateTime lastModifiedDate;
}
// 등록자, 수정자
@Getter
@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
public class BaseEntity extends BaseTimeEntity {
@CreatedBy
@Column(updatable = false)
private String createdBy;
@LastModifiedBy
private String lastModifiedBy;
}
필요한 것을 상속하여 사용하면 된다.
// 사용 어노테이션
@CreatedDate // Entity 생성시 자동으로 시간 저장
@LastModifiedDate // Entity 수정시 자동으로 시간 저장
@CreatedBy // 생성자의 식별값 저장
@LastModifiedBy // 수정자의 식별값 저장
@EntityListeners를 생략하고 싶다면
META-INF/orm.xml 에 특정 xml을 적용하면 된다.
자세한건 강의자료 참고
✔️ Web 확장 - 도메인 클래스 컨버터
HTTP 파라미터로 넘어온 엔티티의 ID로 엔티티 객체를 찾아서 바인딩
// 조회용으로만 사용
@GetMapping("members2/{id}")
public String findMember2(@PathVariable("id") Member member) {
return member.getUsername();
}
❗ 주의
트랜잭션이 없는 범위에서 엔티티를 조회하였기에
엔티티 변경시 DB에 반영 X (더티 체킹 XXX)
✔️ Web 확장 - 페이징과 정렬
@GetMapping("/members")
public Page<Member> list(Pageable pageable) {
Page<Member> page = memberRepository.findAll(pageable);
return page;
}
파라미터 : Pageable
실제 : PageRequest 객체 생성
요청 파라미터
ex) /members?page=0&size=3&sort=id, desc&sort=username, desc
page : 현제페이지, 0부터 시작
size : 한 페이지에 노출할 데이터 건수
sort : 정렬 조건 정의, sort 파라미터 추가, (asc 생략 가능)
기본값
글로벌 설정 : 스프링 부트
spring.data.web.pageable.default-page-size=20 /# 기본 페이지 사이즈/
spring.data.web.pageable.max-page-size=2000 /# 최대 페이지 사이즈/
개별 설정
@PageableDefault 어노테이션 사용
@GetMapping("/members")
public Page<MemberDto> list(@PageableDefault(size = 5) Pageable pageable) {
return memberRepository.findAll(pageable).map(MemberDto::new);
}
접두사
페이징 정보가 둘 이상이면 접두사로 구분
@Qualifier 에 접두사명 추가 "{접두사명}_xxx"
@GetMapping("/memberList")
public Page<MemberDto> list2(@Qualifier("member") @PageableDefault(size = 5) Pageable memberPageable,
@Qualifier("item") @PageableDefault(size = 5) Pageable itemPageable) {
Page<MemberDto> memberDtoPage = memberRepository.findAll(memberPageable).map(MemberDto::new);
Page<Item> itemPage = itemRepository.findAll(itemPageable);
return memberDtoPage;
}
postMan으로 접두사 추가하여 Get 요청
MemberDtoPage 와 ItemPage가 생성
page 1부터 시작하기 <= 이는 문제가 많다.
궁금하면 강의자료를 참조
🔖 학습내용 출처
자바 ORM 표준 JPA 프로그래밍 - 기본편 / 김영한
김영한. (2021). 자바 ORM 표준 JPA 프로그래밍. 에이콘출판사
'Back-End > JPA' 카테고리의 다른 글
스프링 데이터 JPA - 분석 (0) | 2024.07.31 |
---|---|
스프링 데이터 JPA - 페이징과 정렬, 벌크 수정 (0) | 2024.07.29 |
스프링 데이터 JPA - 기본 (0) | 2024.07.29 |
API 학습 내용 (0) | 2024.07.15 |
JPA - JPQL (0) | 2024.07.12 |