값 가져오기
@Query("select m.username from Member m")
List<String> findUsername();
DTO로 직접 조회하기
@Query("select new study.data_jpa.dto.MemberDto(m.id,m.username,t.name) " +
"from Member m join m.team t")
List<MemberDto> findMemberDto();
List -> 컬렉션
단건-> optional도 가능하고 반환타입으로 가능.
단건 조회에서 결과가 없는 경우 -> null 반환 , 2개이상인경우 -> NonUniqueException 반환.
자바 8이 나온 후부터는 Optional을 통해서 반환을 받는다. -> 결과가 있을수도 있고 없을 수도 있는 경우 일단 진행됨.
둘에 대해서 알지 못한듯해서 정리.
SQL로 페이징 정렬을 하는 것은 꽤 어려운편.
-> 순수 JPA의 경우 SQL로 받은다음 setFirstResult를 통해서 몇번째 부터 페이징할건지 정하고
setMaxResult를 통해서 최대 몇개를 가져올건지를 정할수있게됨.
public List<Member> findByPage(int age, int offset,int limit){
return em.createQuery("select m from Member m where m.age = :age order by m.username desc")
.setParameter("age",age)
.setFirstResult(offset)
.setMaxResults(limit)
.getResultList();
}
PageRequest를 통해서 repository에 Paging을 요청할 때 사용함.
PageRequest.of(페이지번호,페이지크기,Sort.by(Sort.Direction.DESC, "username"));
PageRequest pageRequest = PageRequest.of(0, 3, Sort.by(Sort.Direction.DESC, "username"));
Page<Member> page = memberRepository.findByAge(age,pageRequest);
List<Member> content = page.getContent();
//이게 TotalCount
long totalElements = page.getTotalElements();
반환타입을 Page로 할 경우 totalCount Query까지 다 날려줌. -> 따로 구할 필요없음.
테스트를 통해서 실험을해보니 count를 나는 날리지 않았는데 page반환을 받다보니까 알아서 count query가 나가는 모습이다.
Page를 Slice로 바꾸는 경우 PageRequest에서 size에 +1 만큼 가져옴 -> totalCount 같은걸 제공하지 않는다.
-> Slice가 Page보다 상위기 때문에 실수로 반환타입을 Slice로 하고 가져오는걸 Page로 한다해도 돌아가기 때문에 조심해야함.
Count Query를 분리 가능
@Query(value = "select m from Member m",
countQuery = "select count(m.username) from Member m")
Page<Member> findMemberAllCountBy(Pageable pageable);
복잡해지면 성능을 비교하고 분리를 진행해야함. -> 성능차이가없을때는 굳이 안해도됨.
PageRequest.of(0, 3, Sort.by(Sort.Direction.DESC, "username"));
-> 여기서 Sorting 조건이 복잡해지면 안풀리는 경우가 존재하기 때문에 -> 이러한 문제가 생기는 경우 따로 보내는게 맞다.
실무 꿀팁
DTO로 변환하는 법
page.map(member -> new MemberDto(member.getId(),member.getUsername(),null));
page를 맵핑을 통해서 DTO로 손쉽게 반환이 가능하다.