쿼리 메소드 기능(2)

반응형
반응형

페이징 기능

JPA에서 페이징을 할려면,

 public List<Member> findByUsernameAndAgeGraterThen(String username, int age) {
    return em.createQuery("select m from Member m where m.userName =:username and m.age >:age")
        .setFirstResult(1)
        .setMaxResults(10)
        .getResultList();
  }

이런식으로 first와 max를 지정해야 할 수 있다.
코드 상에서는 하드코딩으로 박아두고 있지만, 이것을 밖으로 빼면 될거다. 근데 문제 가 있다.
그건 바로 전체값을 알 수 없다는 점이다. 
결국 계산해야 된다는 건데 솔직히 말하면 귀찮다.

이것을 spring data JPA으로 어떻게 처리할 수 있을까?
바로 이런식으로 처리하면 된다.

@Query("select m.age from Member m")
Page<String> findPagingUserageList(Pageable pageable);

return값이 중요한데, 지금 보는거와 같이 Page와 Slice가 존재한다. 이거는 조금있다 설명하는 걸로 하구
파라미터 값이 Pageable이 되어있는데 이 부분에서 페이징 설정을 하면 된다.
근데 Pageable이란게 인터페이스로 되어있다. 인터페이스로 되어있다는건 이것을 바로 사용이 어렵다는 점이다. 
여러가지 방법이 있겠지만 가장 간단한 방법은

static Pageable ofSize(int pageSize) {
		return PageRequest.of(0, pageSize);
	}

직접 들어가서 확인하는 방법이다. 
확인 해보니 ofSize라는것으로 사이즈만 설정 할 수도 있지만
PageRequest라는 걸로 현재 페이이와 사이즈도 설정이 가능하다. 웬만하면 PageRequest로 사용하면 될것 같다.

protected PageRequest(int page, int size, Sort sort) {
	super(page, size);
	Assert.notNull(sort, "Sort must not be null!");
	this.sort = sort;
}

이런식으로 sort도  정할 수 있다.

아무튼 이것에 대한 이야기는 그만 해도 좋을것 같구
이제 본격적으로 사용해보자.

int getTotalPages();
long getTotalElements();

요런식으로 페이징 갯수와 총 갯수를 알 수 있다.
pageable이라는 곳으로 가면 상세한 정보를 알 수 있다.

int getPageNumber();
int getPageSize();
long getOffset();
Sort getSort();

페이지 갯수, 페이지 크기, offset, 정렬 정보 등을 가져올 수 있다.
Page말고도 Slice도 가져올 수 있다.
Slice는 전체값을 알필요가 없기 때문에 그에 대한 정보를 알 필요가 없다.

이것을 map을 이용해서 dto로 만드는 방법이 존재한다고 한다.

Page<MemberDto> dtos = userageList.map(MemberDto::new);

이런식으로 하면 끝이다.

벌크성 수정 쿼리

데이터를 조작하다보면 단일로 업데이트를 하는 것이 아닌 대량으로 업데이트 처리를 해야하는 상황이 존재하는데
이것을 벌크라고 부른다.

JPA에서는 이런식으로 작성되어진다.

public int updateQuery() {
    return em.createQuery("update Member m set m.age = m.age + 1")
        .executeUpdate();
  }

spring data jpa에서는 어떨까?

간단하다. 

@Query("update Member m set m.age = m.age+1 where m.age >=:age")
int bulkAgePlus(@Param("age") int age);

이렇게 작성하면 되는데 문제는 update다량으로 업데이트를 하게 되면 영속성컨테스트에는 바뀌지 않는 현상이 존재한다.
그 이유는 객체와 데이터의 미묘한 차이때문인데 
데이터 입장에서는 대량으로 업데이트 치는게 자연스럽지만 객체 입장에서는 전체를 전부 가져오지 않는 이상 불가능한 방법이다.
애초에 이런 설계자체가 단일로만 가능하게 설계되어있기 때문에 영속성컨텍스트에는 적용되지 않는다.

그러면 방법이 없을까?
방법은 크게 두가지가 있다.
여기에서 조회를 하지 않고 다른 곳에서 조회하는 방법 가령 메소드가 다르다던지 클래스가 다르다던지..

아니면 영속성컨텍스트를 완전히 지우는 방법
첫번째야 알아서 하면 되고
두번째는 이렇게 하면 된다.

@Modifying(clearAutomatically = true)
@Query("update Member m set m.age = m.age+1 where m.age >=:age")
int bulkAgePlus(@Param("age") int age);

@EntityGraph

JPA에서는 패치 조인이라는 걸 굉장히 많이 사용한다.
이것은 패치 조인을 간단하게 해주는 거라 생각하면 된다.

 @Query("select m from Member m")
  @EntityGraph(attributePaths = {"team"})
  Page<Member> findPagingUserageList(Pageable pageable);

사실 이건 JPA기능이라고 한다.

 

반응형

'JPA' 카테고리의 다른 글

쿼리 메소드 기능(1)  (0) 2022.04.01
JPA 스터디 7주차  (0) 2022.02.26
JPA 스터디 6주차  (1) 2022.02.20
JPA 스터디 5주차  (0) 2022.02.11
JPA 스터디 4주차  (0) 2022.02.02

댓글

Designed by JB FACTORY