springframework/Spring Data JPA

Spring Data Common : 커스텀 리포지토리 생성

Jungsoomin :) 2020. 11. 16. 18:33

부가적으로 varchar 사이즈 255 를 넘을 경우 @ColumnDefinition 이나 @Lob 을 사용한다.

 


직접 함수를 작성하여 리포지토리를 구성하고 싶다.

  • 스프링에서 DAO 를 만드는 것과 같다.
  • 인터페이스에 필요한 메서드를 정의
  • 구현클래스(접미어는 반드시 Impl) 생성 및 @Repository, @Transactional 선언
  • EntityManager 등을 이용한 메서드 작성

만약 구현클래스에 Impl 이라는 접미사 외에 다른 접미사를 채택하고 싶다@EnableRepositoriesrepositoryImplementationPostfix 속성에 원하는 접미사를 제시하면 된다.

 

재정의

  • CustomRepository 인터페이스에 기존 메서드 시그니처를 동일하게 선언하면, JPA 는 사용자가 작성한 메서드를 우선시 하게 되어 재정의가 가능하다.

 

1. 원하는 메서드를 제시한 인터페이스

public interface PostCustomRepository<T> {

    List<Post> findMyPost(); 

    void delete(T entity); // 재정의를 위해 선언
}

2. 인터페이스 다중 상속 방법을 이용해 JpaRepository 상속 인터페이스에 추가로 상속한다.

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

3. @EnableRepositoriesrepositoryImplementationPostfix 속성에 제시한 접미사를 쓰는 구현클래스

@Repository
@Transactional
public class PostCustomRepositoryImpl implements PostCustomRepository<Post> {

    @Autowired
    EntityManager entityManager;

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

    @Override
    public void delete(Post post) {
        System.out.println("Custom Delete");
        entityManager.remove(post);
    }
}

JPA 에서 제공하는 기능인 Dirty Checking + Write Behind 기능으로 인해 insert 및 delete 쿼리는 작동하지 않는다.

@RunWith(SpringRunner.class)
@DataJpaTest
public class PostRepositoryTest {

    @Autowired
    private PostRepository postRepository;

    @Test
    public void crud(){
        Post post = new Post();
        post.setTitle("Hibernate");
        postRepository.save(post);


        postRepository.delete(post);
    }

}
Hibernate: 
    call next value for hibernate_sequence
Custom Delete

 


select 메서드를 insert 밑으로 내리면 Dirty Checking + Write Behind 에 의해 Rollback 될 데이터로 간주(@DataJpaTest@Transactional)하여 delete 작업은 진행되지 않으며 select 를 위해 insert 작업만 작동한다.

@RunWith(SpringRunner.class)
@DataJpaTest
public class PostRepositoryTest {

    @Autowired
    private PostRepository postRepository;

    @Test
    public void crud(){
        Post post = new Post();
        post.setTitle("Hibernate");
        postRepository.save(post);

        postRepository.findMyPost();

        postRepository.delete(post);
    }

}
Hibernate: 
    call next value for hibernate_sequence
Custom findMyPost
Hibernate: 
    insert 
    into
        post
        (content, created, title, id) 
    values
        (?, ?, ?, ?)
2020-11-16 18:15:49.388 TRACE 1228 --- [           main] o.h.type.descriptor.sql.BasicBinder      : binding parameter [1] as [CLOB] - [null]
2020-11-16 18:15:49.394 TRACE 1228 --- [           main] o.h.type.descriptor.sql.BasicBinder      : binding parameter [2] as [TIMESTAMP] - [null]
2020-11-16 18:15:49.396 TRACE 1228 --- [           main] o.h.type.descriptor.sql.BasicBinder      : binding parameter [3] as [VARCHAR] - [Hibernate]
2020-11-16 18:15:49.402 TRACE 1228 --- [           main] o.h.type.descriptor.sql.BasicBinder      : binding parameter [4] as [BIGINT] - [1]
Hibernate: 
    select
        post0_.id as id1_0_,
        post0_.content as content2_0_,
        post0_.created as created3_0_,
        post0_.title as title4_0_ 
    from
        post post0_
2020-11-16 18:15:49.426 TRACE 1228 --- [           main] o.h.type.descriptor.sql.BasicExtractor   : extracted value ([id1_0_] : [BIGINT]) - [1]
Custom Delete

@Rollback(false) 를 지정하면 딜리트 쿼리를 날리게 된다.

@RunWith(SpringRunner.class)
@DataJpaTest
public class PostRepositoryTest {

    @Autowired
    private PostRepository postRepository;

    @Test
    @Rollback(false)
    public void crud(){
        Post post = new Post();
        post.setTitle("Hibernate");
        postRepository.save(post);

        postRepository.findMyPost();

        postRepository.delete(post);
    }

}
Hibernate: 
    call next value for hibernate_sequence
Custom findMyPost
Hibernate: 
    insert 
    into
        post
        (content, created, title, id) 
    values
        (?, ?, ?, ?)
2020-11-16 18:17:35.132 TRACE 6988 --- [           main] o.h.type.descriptor.sql.BasicBinder      : binding parameter [1] as [CLOB] - [null]
2020-11-16 18:17:35.134 TRACE 6988 --- [           main] o.h.type.descriptor.sql.BasicBinder      : binding parameter [2] as [TIMESTAMP] - [null]
2020-11-16 18:17:35.136 TRACE 6988 --- [           main] o.h.type.descriptor.sql.BasicBinder      : binding parameter [3] as [VARCHAR] - [Hibernate]
2020-11-16 18:17:35.138 TRACE 6988 --- [           main] o.h.type.descriptor.sql.BasicBinder      : binding parameter [4] as [BIGINT] - [1]
Hibernate: 
    select
        post0_.id as id1_0_,
        post0_.content as content2_0_,
        post0_.created as created3_0_,
        post0_.title as title4_0_ 
    from
        post post0_
2020-11-16 18:17:35.164 TRACE 6988 --- [           main] o.h.type.descriptor.sql.BasicExtractor   : extracted value ([id1_0_] : [BIGINT]) - [1]
Custom Delete
Hibernate: 
    delete 
    from
        post 
    where
        id=?
2020-11-16 18:17:35.252 TRACE 6988 --- [           main] o.h.type.descriptor.sql.BasicBinder      : binding parameter [1] as [BIGINT] - [1]