Spring-Data-JPA 주석에 대한 setMaxResults?


127

Spring-Data-JPA를 프로젝트에 통합하려고합니다. 나를 혼란스럽게하는 한 가지는 주석으로 setMaxResults (n)을 어떻게 달성합니까?

예를 들어, 내 코드 :

public interface UserRepository extends CrudRepository<User , Long>
{
  @Query(value="From User u where u.otherObj = ?1 ")
  public User findByOhterObj(OtherObj otherObj);
}

one (and only one)otherObj에서 User 를 반환하기 만하면되지만 maxResults에 주석을다는 방법을 찾을 수 없습니다. 누군가 나에게 힌트를 줄 수 있습니까?

(mysql은 다음과 같이 불평합니다.

com.mysql.jdbc.JDBC4PreparedStatement@5add5415: select user0_.id as id100_, user0_.created as created100_ from User user0_ where user0_.id=2 limit ** NOT SPECIFIED **
WARN  util.JDBCExceptionReporter - SQL Error: 0, SQLState: 07001
ERROR util.JDBCExceptionReporter - No value specified for parameter 2

)

링크를 찾았습니다 : https://jira.springsource.org/browse/DATAJPA-147 , 시도했지만 실패했습니다. 지금은 불가능한 것 같나요? 왜 그런 중요한 기능이 Spring-Data에 내장되어 있지 않습니까?

이 기능을 수동으로 구현하는 경우 :

public class UserRepositoryImpl implements UserRepository

에서 미리 정의 된 수많은 메서드를 구현해야합니다 CrudRepository. 이것은 끔찍할 것입니다.

환경 : spring-3.1, spring-data-jpa-1.0.3.RELEASE.jar, spring-data-commons-core-1.1.0.RELEASE.jar

답변:


176

SpringData JPA 1.7.0 (Evans 릴리스 트레인) 기준.

다음과 같이 쿼리 메서드를 정의 할 수있는 새로 도입 된 키워드 TopFirst키워드를 사용할 수 있습니다.

findTop10ByLastnameOrderByFirstnameAsc(String lastname);

SpringData는 사용자가 정의한 숫자로 결과를 자동으로 제한합니다 (생략 된 경우 기본값은 1). 결과의 순서는 여기에서 관련됩니다 ( OrderBy예제에 표시된 절을 통해 또는 Sort메서드에 매개 변수를 전달하여 ). SpringData Evans 릴리스 트레인의 새로운 기능을 다루는 블로그 게시물 또는 문서 에서 이에 대한 자세한 내용을 읽어보십시오 .

이전 버전의 경우

데이터 조각 만 검색하기 위해 SpringData Pageable는 요청 측 의 인터페이스 와 함께 제공되는 페이지 매김 추상화를 사용하고 Page사물의 결과 측에 대한 추상화를 사용합니다. 그래서 당신은

public interface UserRepository extends Repository<User, Long> {

  List<User> findByUsername(String username, Pageable pageable);
}

다음과 같이 사용하십시오.

Pageable topTen = new PageRequest(0, 10);
List<User> result = repository.findByUsername("Matthews", topTen);

결과의 컨텍스트를 알아야하는 경우 (실제로 어떤 페이지입니까? 첫 번째 페이지입니까? 총 몇 개입니까?) Page반환 유형으로 사용하십시오.

public interface UserRepository extends Repository<User, Long> {

  Page<User> findByUsername(String username, Pageable pageable);
}

클라이언트 코드는 다음과 같이 할 수 있습니다.

Pageable topTen = new PageRequest(0, 10);
Page<User> result = repository.findByUsername("Matthews", topTen);
Assert.assertThat(result.isFirstPage(), is(true));

Page메타 데이터를 계산하기 위해 총 요소 수를 알아 내야하므로 리턴 유형으로 사용 하는 경우 실행할 실제 쿼리의 카운트 프로젝션을 트리거하지는 않습니다 . 그 외에도 PageRequest안정적인 결과를 얻으려면 실제로 에 정렬 정보를 장착해야합니다 . 그렇지 않으면 쿼리를 두 번 트리거하고 데이터가 변경되지 않은 경우에도 다른 결과를 얻을 수 있습니다.


14
감사합니다.하지만 여전히 '주석 기반'솔루션을 원합니다. 이 경우 'Page / Pageable'이 너무 과도하기 때문입니다. 그리고 클라이언트는 '하나 뿐인'결과를 검색하기 위해 Pageable / Page를 만들어야합니다 ... 사용하기가 매우 비우호적입니다. 그리고 여러분이 Spring-Data를 담당하고있는 것 같습니다 . 이 문제를 더 자세히 살펴볼 수 있기를 바랍니다. stackoverflow.com/questions/9276461/… Spring-Data의 버그인지 확인할 수 있습니까?
smallufo

1
+ 이것은 작동하지만, 주석 기반 솔루션은 최신 버전에서 더 좋을 것입니다
azerafati 2014-06-28

1
제한된 쿼리를 원할 경우 완전히 필요없는 개수 쿼리가 여기에서 실행됩니다.
azerafati 2014 년

1
List메서드의 반환 유형으로 사용 하는 경우가 아닙니다 .
Oliver Drotbohm 2014 년

3
내가 생각 Top하고 First키워드를 사용하는 방법에 적용되지 않습니다 @Query주석을? 메소드 이름 기반 쿼리 생성을 사용하는 것만?
루슬란 Stelmachenko

106

Java 8 및 SpringData 1.7.0을 사용하는 경우 @Query최대 결과 설정과 주석 을 결합하려면 기본 메소드를 사용할 수 있습니다 .

public interface UserRepository extends PagingAndSortingRepository<User,Long> {
  @Query("from User u where ...")
  List<User> findAllUsersWhereFoo(@Param("foo") Foo foo, Pageable pageable);

  default List<User> findTop10UsersWhereFoo(Foo foo) {
    return findAllUsersWhereFoo(foo, new PageRequest(0,10));
  }

}

3
하나의 결과에 대한 잠재적으로 유용한Stream<User> ... {...} default Optional<User> ... { ...findAny() }
xenoterracide

28

다음과 같이 "주석 별 setMaxResults (n)"에 해당하는 것을 제공 할 수있는 방법이 있습니다.

public interface ISomething extends JpaRepository<XYZ, Long>
{
    @Query("FROM XYZ a WHERE a.eventDateTime < :before ORDER BY a.eventDateTime DESC")
    List<XYZ> findXYZRecords(@Param("before") Date before, Pageable pageable);
}

이것은 페이징 가능이 매개 변수로 전송 될 때 트릭을 수행해야합니다. 예를 들어 처음 10 개의 레코드를 가져 오려면 페이징 가능을 다음 값으로 설정해야합니다.

new PageRequest(0, 10)

Pagable을 사용하는 경우 List <XYZ>가 아닌 Page <XYZ> 반환
Arundev

@Arundev 잘못됨- List완벽하게 작동합니다 ( 이전 의견count 에서 이미 언급했듯이 불필요한 쿼리를 피합니다 )
Janaka Bandara

21

SpringData Evans 사용 (1.7.0 RELEASE)

함께라는 모듈의 또 다른 목록 봄 데이터 JPA의 새로운 릴리스 에반스 키워드를 사용하는 기능을 가지고 Top20First, 쿼리 결과를 제한하기를

그래서 당신은 지금 쓸 수 있습니다

List<User> findTop20ByLastname(String lastname, Sort sort);

또는

List<User> findTop20ByLastnameOrderByIdDesc(String lastname);

또는 단일 결과

List<User> findFirstByLastnameOrderByIdDesc(String lastname);

5
선택적 <사용자> findFirstByLastnameOrderByIdDesc (문자열 성);
krmanish007

상위 20 개 결과를 얻은 후 페이지 매김을 사용하여 웹 사이트의 다음 페이지로 이동할 때 다음 20 개의 결과를 어떻게 얻습니까?
kittu

@kittu, 물론 또 다른 질문이지만 Pageable객체 를 전달해야 합니다. 봄 문서를 체크 아웃
azerafati

FIRST로 지정된 경우 메서드가 망할 List를 반환하는 이유는 무엇입니까?
Vasile Surdu

13

나에게 가장 적합한 선택은 네이티브 쿼리입니다.

@Query(value="SELECT * FROM users WHERE other_obj = ?1 LIMIT 1", nativeQuery = true)
User findByOhterObj(OtherObj otherObj);

확실하지 한도는 최대 절전 모드에서 지원되는 경우 : forum.hibernate.org/viewtopic.php?f=9&t=939314
의 Witold Kaczurba

2
전체 개념을 깨뜨립니다! 대신 EntityManager를 더 잘 사용하십시오!
Spektakulatius

@ Code.IT 나는 KISS 개념을 전파합니다. 그 JPA nativeQuery 주석 매개 변수를 제외 하고 무시하지 않도록 추가되었습니다.
Grigory Kislin

@GKislin은 findLimitOneByOtherObj와 같은 메서드의 이름을 변경해야합니다. 또한 other_obj가 고유하지 않은 경우 잘못된 결과를 초래하는 OrderBy를 추가하는 것을 잊었습니다. 그렇지 않으면 고유 한 컬럼에 어디 문은 제한 하나없이 충분합니다
Spektakulatius

LIMIT 키워드는 최대 절전 모드가 아니지만 postgres / mysql
Acewin

5

클래스가 @Repository확장 되면 JpaRepository아래 예제를 사용할 수 있습니다.

int limited = 100;
Pageable pageable = new PageRequest(0,limited);
Page<Transaction> transactionsPage = transactionRepository.findAll(specification, pageable);
return transactionsPage.getContent();

getContent는 List<Transaction>.


쿼리에 transactionRepository.findByFirstNameAndLastName (firstname, lastname)과 같은 2 개의 where 조건이 있으면 어떻게됩니까? 작동할까요? 이 예외가 발생합니다. org.springframework.data.mapping.PropertyReferenceException : 유형 Board에 대한 속성 생성이 없습니다.
Shailesh

4

@QueryHints를 사용하는 것도 가능합니다. 예제는 org.eclipse.persistence.config.QueryHints # JDBC_MAX_ROWS를 사용합니다.

@Query("SELECT u FROM User u WHERE .....")
@QueryHints(@QueryHint(name = JDBC_MAX_ROWS, value = "1"))
Voter findUser();

이 코드를 테스트했지만 작동하지 않습니다. 예외는 아니지만 적절한 결과는 더 적습니다. 또한 문서는 QueryHint에 대해 매우 얇습니다. 아래를 참조하십시오. docs.spring.io/spring-data/jpa/docs/1.7.1.RELEASE/reference/...
bogdan.rusu

IIRC에서는 쿼리 힌트를 따를 것이라는 보장 이 없습니다 . 구현에 "친근한 권장 사항"을 전달하는 방법 일뿐입니다.
Priidu Neemre

나는 그것을 시도 @QueryHints({@QueryHint(name = org.hibernate.annotations.FETCH_SIZE, value = "1")})최대 절전 모드에서, 그러나 별명 :( 작동하지 않습니다
그리고 리 Kislin

2
org.hibernate.annotations.FETCH_SIZE 그것의 가져 오기 크기, 최대 결과가 아니라 제한이 아닙니다. Hiber cant
Zhuravskiy Vitaliy

4

new PageRequest(0,10)최신 Spring 버전에서 작동하지 않습니다 (사용하고 있습니다 2.2.1.RELEASE). 기본적으로 생성자는 추가 매개 변수를 Sort유형 으로 갖습니다. 또한 생성자는 protected자식 클래스 중 하나를 사용하거나 of정적 메서드를 호출해야합니다 .

PageRequest.of(0, 10, Sort.sort(User.class).by(User::getFirstName).ascending()))

Sort매개 변수 사용을 생략 하고 암시 적으로 기본 정렬 (pk 기준 정렬 등)을 사용할 수도 있습니다.

PageRequest.of(0, 10)

함수 선언은 다음과 같아야합니다.

List<User> findByUsername(String username, Pageable pageable)

기능은 다음과 같습니다.

userRepository.findByUsername("Abbas", PageRequest.of(0,10, Sort.sort(User.class).by(User::getLastName).ascending());
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.