데이터 JPA 는 인터페이스를 통해 개발을 완료할 수 있는 기술인데, 데이터 JPA 로는 부족하여 직접 구현하고 싶다면 어떻게 해야할까?
리포지토리 인터페이스를 추가로 생성하여 메서드를 정의한다.
추가한 인터페이스에 구현체 클래스를 만들어 메서드를 구현한다. (구현 클래스의 이름은 추가한 리포지토리 인터페이스 이름 + Impl 이여야 함, 변경하고 싶다면 설정도 가능)
추가한 인터페이스를 데이터 JPA 로 구현체 없이 사용하는 인터페이스가 상속하도록 한다.
참고.
실무에서 사용자 정의 리포지토리는 주로 동적 쿼리 작성을 위한 Querydsl이나, jdbc template 에 사용된다.
사용자 정의 리포지토리가 아니라, 직접 빈에 등록하여 리포지토리 클래스를 구현해도 된다. 관심사가 같은데, 스프링 데이터 JPA로는 부족할 때 사용하자.
엔티티를 생성, 변경할 때 변경한 사람과 시간을 추적하고 싶다면 어떻게 해야할까?
필요한 공통 필드들(등록일, 수정일, 등록자, 수정자 등)을 담은 클래스를 정의한다.
@PrePersist로 영속되기 직전에 실행될 로직, @PreUpdate로 수정되기 직전에 실행될 로직을 클래스 내에 정의한다. (영속 이후, 수정 이후 로직을 관리하는 @Postxxx 도 존재)
@MappedSuperclass 를 클래스에 붙여 엔티티에서 상속 시 해당 필드들도 함께 관리할 수 있도록 설정한다.
공통 필드가 필요한 엔티티에 추가한 클래스를 상속한다.
스프링 부트 설정 클래스에 @EnableJpaAuditing 을 적용한다.
공통 필드들을 정의한 클래스를 정의하고, @MappedSuperclass, @EntityListeners(AuditingEntityListener.class) 를 클래스에 적용한다.
로직을 정의할 필요 없이, 필드들에 @CreatedDate, @LastModifiedDate 를 사용하여 등록일 수정일을 관리할 수 있다.
공통 필드가 필요한 엔티티에 추가한 클래스를 상속한다.
추가. 등록자, 수정자가 필요하다면?
공통 필드에 @CreatedBy, @LastModifiedBy 를 추가한다.
스프링 부트 설정 클래스에 AuditorAware 빈을 등록한다.
빈에 해당 유저를 식별할 수 있는 정보를 반환하는 람다 함수를 제공한다. (ex. 스프링 시큐리티로 유저 정보 가져오기, HTTP session 에서 유저 정보 가져오기 등)
참고.
스프링 데이터 JPA 사용 방법에서 @EntityListeners 어노테이션은 xml 파일에 정의하여 전역 설정할수도 있다.
tip. 등록/수정 시간 정보는 대부분의 엔티티에서 필요하지만, 등록자/수정자는 일부 엔티티에서만 필요하다면?
시간 정보를 담은 클래스를 정의하고, 해당 클래스를 상속받아 등록자, 수정자를 담은 클래스를 정의해둔 뒤, 엔티티마다 가져다 사용하면 깔끔하게 해결할 수 있다.