아카이브

[스프링 데이터 JPA] 스프링 데이터 Common 7. Custom Repository 만들기 본문

Spring/스프링 데이터 JPA

[스프링 데이터 JPA] 스프링 데이터 Common 7. Custom Repository 만들기

주멘이 2021. 1. 16. 21:17

쿼리 메서드(쿼리 생성 및 미리 정의된 쿼리 찾기)로 해결되지 않는 경우 직접 구현 가능

  • 스프링 데이터 리포지토리 인터페이스에 기능 추가
  • 스프링 데이터 리포지토리 기본 기능 덮어쓰기 가능

구현 방법

  1. 커스텀 리포지토리 인터페이스 정의
  2. 인터페이스 구현 클래스 만들기 (기본 접미어는 Impl)
  3. 엔티티 리포지토리에 커스텀 리포지토리 인터페이스 추가  

 

PostCustomRepository 인터페이스 정의

public interface PostCustomRepository<T> {

    List<Post> findMyPost();
    
    void delete(T entity);	// 기본 기능 재정의하기 (사용자 정의 구현체가 spring-data-jpa 보다 우선순위가 높다)
}

 

PostCustomRepository 인터페이스 구현체 PostCustomRepositoryImpl 정의

@Repository
public class PostCustomRepositoryImpl implements PostCustomRepository<Post> {

    @Autowired
    EntityManager entityManager;

    @Override
    public List<Post> findMyPost() {
        return entityManager.createQuery("SELECT p FROM Post AS p", Post.class).getResultList();
    }

    @Override
    public void delete(Post entity) {
        entityManager.remove(entity);
    }
}

 

PostRepository 인터페이스에 커스텀 레포지토리 인터페이스 상속 추가하기

public interface PostRepository extends JpaRepository<Post, Long>, PostCustomRepository<Post> {

    Page<Post> findByTitleContains(String title, Pageable pageable);

    long countByTitleContains(String title);

}

 

테스트 코드

  • JPA 객체 상태에 따라 쿼리가 실제로 날아가지 않을 수도 있다.
  • Hibernate가 판단하기 때문.
  • 테스트 코드 작성 시, 객체 상태에 따른 이해가 중요하다.
    @Test
    public void customTest() {
        Post post = new Post();
        post.setTitle("custom");
        postRepository.save(post);  // select가 필요하다가고 hibernate가 판단하여 flushing이 일어나서 insert query exec
        postRepository.findMyPost();

        /**<delete query가 실행되지 않았던 이유>
         * entityManager가 removed 상태로 변경시켰지만, 실제로 DB sync는 하지 않는다.
         * @Transactional이 붙어있는 스프링의 모든 테스트는 기본적으로 ROLLBACK 트랜잭션이다.
         * Hibernate는 ROLLBACK 트랜잭션의 경우 필요없는 query는 실행하지 않는다.
         */
        postRepository.delete(post);

        postRepository.flush(); // 하지만 강제로 flush()를 호출하면 query를 실행한다.

    }

구현체 접미어 변경하기

  • 기본값으로는 Impl이지만, 변경하고 싶다면 메인 Application에서 설정이 가능하다.
@SpringBootApplication
@EnableJpaRepositories(queryLookupStrategy = QueryLookupStrategy.Key.CREATE_IF_NOT_FOUND
        , repositoryImplementationPostfix = "Impl")
@Import(JumenRegister.class)
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

}