[Spring] Spring Data JPA(3)

99winnmin·2022년 7월 22일
0

Spring

목록 보기
13/17

QueryMethod 살펴보기

public interface JpaUserRepository extends JpaRepository<JpaUser, Long> {
    Set<JpaUser> findByName1(String name);
    Optional<JpaUser> findByName2(String name);
    List<JpaUser> findByName3(String name);
}

다음과 같이 리턴형을 자유롭게 지정하여 여러가지 값을 받을 수 있으나 Runtime시 에러가 날 수 있기 때문에 잘 지정해줘야함.

https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#repositories.query-methods.details
Spring JPA 공식문서를 통해 Query Method를 어떻게 다루는지 상세히 볼 수 있음

select query

find...By, read...By등과 같이 자유도 있게 select query문을 사용할 수 있다.

	JpaUser findByEmail(String email);

    JpaUser getByEmail(String email);

    JpaUser readByEmail(String email);

    JpaUser queryByEmail(String email);

    JpaUser searchByEmail(String email);

    JpaUser streamByEmail(String email);

    JpaUser findJpaUserByEmail(String email);

    JpaUser findSomethingByEmail(String email);

그러나 높은 자유도로 인해 다음과 같은 query method도 가능하지 않을까라는 생각이 떠오를 수도있다.

JpaUser findSomethingByEmail(String email);
  • 다음과 같이 ... 사이에 원래 Entity를 넣어야하지만 아무 문자열을 넣어도 잘 동작한다. 이를 보면 중간에 들어가는 문자열이 무시됨을 알 수 있고 이는 엄청난 자유도를 보장한다. 그러나 이는 코드 가독성을 떨어뜨리기 때문에 지양하도록하고 가독성을 높일 수 있도록 의미있는 문자열을 사용하도록하자
  • IDE에서 자동완성을 이용하다가 findByByName과 같은 이름을 만들수도 있는데 이는 Runtime에서 오류가 난다 -> creation한 query method들에 대해서는 test를 꼭 하도록하자!!

exists...By, count...By, delete...By, remove...By

  • 많이 사용되지 않는다...
  • exists...By : find...By를 이용해서 존재 여부 체크해서 잘 안씀
  • count...By : find...By를 이용해서 가져온 entity개수를 세서 잘 안씀
  • delete...By, remove...By : 일반적으로 JPA repo method를 쓰기 때문에 delete query method는 잘 안씀

select query에 접두어 붙이기(ex Top<'number>...)

	JpaUser findFirst1ByName(String name);
    JpaUser findTop1ByName(String name);

    List<JpaUser> findFirst2ByName(String name);
    List<JpaUser> findTop2ByName(String name);

Refer Doc에서 나와있는 First,Top과 같은 접두어는 다음과 같이 사용하면서 정상작동한다.

    JpaUser findLast1ByName(String name);

그러나 다음과 같이 제공되어있지 않은 문자열은 무시가 되어 findByName과 같이 동작하게 되는데 Last1을 동작하게 해주고 싶다면 order by를 역순으로 지정해준후 findTop1ByName으로 찾아와야 한다.

Query Method에 다양한 조건 추가하기

https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#appendix.query.method.predicate
해당 정보와 같이 여러가지 조건을 개발자가 추가할 수 있다.

  • 조건을 추가한 다양한 query method
@Test
    void 다양한쿼리메서드(){
        // ===================== QueryMethod + 조건 추가====================
        System.out.println("findByEmailAndName : "+jpaUserRepository.findByEmailAndName("ojysep2@gmail.com","seung"));
        System.out.println("findByEmailOrName : "+jpaUserRepository.findByEmailOrName("ojysep2@gmail.com","ryu"));
//        System.out.println("findByCreatedAtAfter : "+jpaUserRepository.findByCreatedAtAfter(LocalDateTime.now().minusDays(1L)));
        jpaUserRepository.findByCreatedAtAfter(LocalDateTime.now().minusDays(1L)).forEach(System.out::println);
        jpaUserRepository.findByIdAfter(2L).forEach(System.out::println);

        System.out.print("findByCreatedAtGreaterThan : ");
        jpaUserRepository.findByCreatedAtGreaterThan(LocalDateTime.now().minusDays(1L)).forEach(System.out::println);

        System.out.print("findByCreatedAtGreaterThanEqual : ");
        jpaUserRepository.findByCreatedAtGreaterThanEqual(LocalDateTime.now().minusDays(1L)).forEach(System.out::println);

        System.out.print("findByCreatedAtBetween : ");
        jpaUserRepository.findByCreatedAtBetween(
                LocalDateTime.now().minusDays(1L),
                LocalDateTime.now().plusDays(1L)).forEach(System.out::println);

        System.out.print("findByIdBetween : ");
        jpaUserRepository.findByIdBetween(1L,4L).forEach(System.out::println);

        System.out.println("findByIdIsNotNull : "+jpaUserRepository.findByIdIsNotNull());
        // System.out.println("findByAddressIsNotEmpty : "+jpaUserRepository.findByAddressIsNotEmpty());

        jpaUserRepository.findByNameIn(Lists.newArrayList("ryu", "seung")).forEach(System.out::println);

        System.out.println("findByNameStartingWith : "+jpaUserRepository.findByNameStartingWith("ry"));
        System.out.println("findByNameEndingWith : "+jpaUserRepository.findByNameEndingWith("ng"));
        System.out.println("findByNameStartingWith : "+jpaUserRepository.findByNameContains("bo"));
        // like는 코드 가독성을 해침!
        System.out.println("findByNameLike : "+jpaUserRepository.findByNameLike("%y%"));

        // Is,Equals 은 코드 가독성을 높이는 친구들임
        // findByName == findByNameIs == findByNameEquals
    }

Query 정렬

코드가 너무 더럽지 않게 가독성있게 name하고 구성하는 것이 중요하다...

	@Test
    void 정렬쿼리메소드(){
        System.out.println("findTop1ByName : "+jpaUserRepository.findTop1ByName("ryu"));
        System.out.println("findTopByNameOrderByIdDesc : "+jpaUserRepository.findTopByNameOrderByIdDesc("ryu"));

        System.out.println("findAllOrderByIdDesc : ");
        jpaUserRepository.findAll(Sort.by(Sort.Direction.DESC, "id")).forEach(System.out::println);

        System.out.println("findFirstByNameOrderByIdDescEmailAsc : ");
        jpaUserRepository.findFirstByNameOrderByIdDescEmailAsc("ryu").forEach(System.out::println);

        System.out.println("findFirstByNameWithSortParam : ");
        jpaUserRepository.findFirstByName("ryu", Sort.by(Sort.Order.desc("id"),Sort.Order.asc("email")))
                .forEach(System.out::println);
        jpaUserRepository.findFirstByName("ryu", getSort()).forEach(System.out::println);
    }

    private Sort getSort(){
        return Sort.by(
                Sort.Order.desc("id"),
                Sort.Order.asc("email"),
                Sort.Order.desc("createdAt"),
                Sort.Order.asc("updatedAt")
        );
    }

Query로 페이징 처리

코드에 나와있는 것 이상으로 Page,Pageable,Slice 인터페이스를 보면 사용 가능한 기능들이 많다.
^+click으로 한번씩 확인해보는 것이 좋을 것 같다.

	@Test
    void 쿼리로페이징처리(){
        System.out.println("findByNameWithPaging : " + jpaUserRepository.findByName(
                "ryu",
                PageRequest.of(0, 1, Sort.by(Sort.Order.desc("id")))).getContent()); // 0페이지 요청+페이지당 데이터 1개+id역순
        System.out.println("findByNameWithPaging : " + jpaUserRepository.findByName(
                "ryu",
                PageRequest.of(0, 1, Sort.by(Sort.Order.desc("id")))).getTotalElements());
    }

출처 : 한 번에 끝내는 Java/Spring 웹 개발 마스터 초격차 패키지 Online.

profile
功在不舍

0개의 댓글