스프링데이터 + JPA 112

16. 스프링 데이터 JPA 페이징, 정렬

스프링 데이터 JPA에서 페이징과 정렬을 정말 간단히 지원해 준다. 스프링 데이터 JPA는 페이징과 정렬을 표준화 시켜놨다. org.springframework.data.domain.Sort 와 org.springframework.data.Pageable 이 두개로 표준화 시켜놨음. 페이징도 요새는 2가지 종류가 있는데, 추가 count 결과를 포함하는 페이징과, 추가 count 결과를 포함하지 않는, 다음 페이지가 있나 없나 확인 가능한(내부적으로 limit + 1 하나 더 조회) 왜 모바일 같은 경우 아래로 내리면 그냥 더 나오는.. org.springframework.data.Page가 총 count가 몇갠지 추가로 쿼리를 날리는 페이징이고, org.springframework.data.Slice가..

15. 순수 JPA 페이징, 정렬

지금까지 뭐 select * from member; 이런 식으로 그냥 다 데려왔었는데, 우리가 DB에 있는 걸 사실 다 끌고 올 수는 없음. 적당한 단위로 끊어서 가지고 와야 함. 그래서 게시판 보면 페이지별로 끊어놓는 거임. 조건 나이가 10살 이름으로 내림차순 첫번째 페이지. 페이지당 보여줄 데이터는 3건 public List findByPage(int age, int offset, int limit){ return em.createQuery("select m from Member m where m.age = :age order by m.username desc", Member.class) .setParameter("age", age) .setFirstResult(offset) .setMaxResul..

14. 스프링 데이터 JPA 반환 타입

스프링 데이터 JPA는 이 조회해는 것의 반환타입을 유연하게 제공함. 컬렉션으로, 아니면 단건, 아니면 단건인데 Optional로 등등.. List findListByUsername(String username); Member findMemberByUsername(String username); Optional findOptionalByUsername(String username); 굉장히 많은 반환타입이 보장된다. 컬렉션, 단건, 옵셔널 이거 외에도 많다. 컬렉션은 없으면 그냥 빈 컬렉션. 단건은 null. 이게 조금 순수 JPA와 다른 부분인데 순수 JPA는 없으면 예외를 날리는 데 스프링 데이터 JPA는 그 예외를 잡아서 null로 return함. 옵셔널은 마치 양자처럼 있거나 없거나. 이 외에도 ..

13. 파라미터 바인딩

파라미터 바인딩은 위치기반이 있고 이름기반이 있음 select m from Member m where m.username = ?0 select m from Member m where m.usernmae = :name 위치기반은 사용하지 않는다고 함. 확실히 이름기반이 훨씬 명확함. @Query("select m from Member m where m.username = :username and m.age = :age") List findUser(@Param("username") String username, @Param("age") int age); 이렇게 바인딩 했었음. @Param(SQL상파라미터명) 타입 인자이름 여튼 이런거는 지금까지 많이 해왔던 거고, 컬렉션을 인자로 넣을 수 있는데 이게 무슨 ..

12. Dto나 테이블 중 특정 값만 조회해 오기

지금까지 그냥 엔티티 전체를 가지고 왔음. 이번엔 스프링 데이터 JPA로 Dto나 특정 값만 가져오는 걸 해 볼텐데, 이거는 메소드명으로 쿼리 자동생성으로는 못한다. 저 익명@Query를 써야 한다. @Query("select m.username from Member m") List findUsernames(); 그냥 우리가 순수 JPA에서 jpql 짜듯이 하면 된다. 그럼 다음은 Dto @Data public class MemberDto { private Long id; private String username; private String teamName; public MemberDto(Long id, String username, String teamName) { this.id = id; this...

11. @Query, 메소드에 쿼리 정의

그냥 @Query("select m from Member m where m.username = :username and m.age = :age") List findUser(@Param("username") String username, @Param("age") int age); 이렇게 곧바로 쓰는거다. 이거는 네임드쿼리를 곧바로 쓰는거라고 보면 된다. @Query("select m from Member m where m.username = :username and m.age = :age") List findUser(@Param("username") String username, @Param("age") int age); @Query("쿼리와 :파라미터") List 메소드명(@Param("쿼리상파라미터명"..

10. JPA 네임드 쿼리

얘는 실무에서 거의 쓸 일이 없음. 네임드 쿼리는 쿼리에 이름을 부여하고 호출하는 기능 이거보다 더 상위호환이 될 수 있는 좋은 기능이 있기에 이거는 잘 안씀. 그래도 소개를 해 보자면, 사용하려면 @NamedQuery( name = "Member.findByUsername", query="select m from Member m where m.username=:username" ) public class Member { ... 이렇게 엔티티에 적어놓음( 따로 xml파일에 정의해 놓을 수도 있음. ) public List findByUsernameNameQuery(String username){ return em.createNamedQuery("Member.findByUsername",Member.cla..

9. 메소드 이름으로 쿼리 생성

Spring Data JPA 에서 제공하는 공통 기능 말고도, 예를 들어 username으로 조회를 해 온다던지, 이런 도메인에 특화된 조회 등 공통되지 않은 부분들을 만들어야 할 필요성이 있다. Spring Data JPA는 이러 한 공통적인 부분이 아닌 쿼리들을 어떻게 만들도록 지원해 주는지 알아볼 것이다. Spring Data JPA에서 쿼리를 만들도록 지원해 주는 것은 총 3가지 방법이 있는데, 1. 메소드 이름으로 쿼리 생성 2. JPA NamedQuery 호출 3. @Query 어노테이션을 사용해서 리파지토리 인터페이스에 쿼리 직접 정의 먼저 메소드 이름으로 쿼리 생성하는 것에대해 알아볼 거임. 그 전에, Jpa로만 먼저 짜보면 username이 같고 age가 특정 값 보다 큰거 public ..

8. 공통 인터페이스 분석

이번엔 public interface MemberRepository extends JpaRepository { } 여기의 JpaRepository 등의 안으로 들어가, 분석해 볼거임. package org.springframework.data.jpa.repository; @NoRepositoryBean public interface JpaRepository extends ListCrudRepository, ListPagingAndSortingRepository, QueryByExampleExecutor { void flush(); S saveAndFlush(S entity); List saveAllAndFlush(Iterable entities); @Deprecated default void delete..

7. 공통 인터페이스 적용

적용.. 그냥 봤던대로, public interface TeamRepository extends JpaRepository { } public interface 리포지토리명 extends JpaRepository { } 끝. @Test public void basicCRUD(){ Member member1 = new Member("member1", 10); Member member2 = new Member("member2", 11); memberRepository.save(member1); memberRepository.save(member2); Member findMember1 = memberRepository.findById(member1.getId()).get(); Member findMember2 ..