본문 바로가기
Spring/Spring Data Jpa

5. 확장 기능

by wch_t 2024. 4. 11.

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