Spring-Data-JPAアノテーションのsetMaxResults?


127

Spring-Data-JPAをプロジェクトに組み込もうとしています。私を混乱させる1つのことは、アノテーションによって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

回答:


175

Spring Data JPA 1.7.0(Evansリリーストレイン)以降。

新しく導入されたTopFirstキーワードを使用すると、次のようなクエリメソッドを定義できます。

findTop10ByLastnameOrderByFirstnameAsc(String lastname);

Spring Dataは自動的に結果を定義した数に制限します(省略された場合のデフォルトは1です)。結果の順序がここで関連することに注意してください(OrderBy例に示されている節を通じて、またはSortパラメーターをメソッドに渡すことによって)。詳細については、Spring Data Evansリリーストレインの新機能をカバーするブログ投稿またはドキュメントを参照してください

以前のバージョンの場合

データのスライスのみを取得するために、Spring Dataは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安定した結果を得るために、実際ににソート情報を装備してください。そうしないと、クエリを2回トリガーして、データが変更されていなくても異なる結果が得られる可能性があります。


14
おかげで、私はまだ「注釈ベース」のソリューションを期待しています。この場合、「ページ/ページング可能」はやりすぎです。そして、クライアントは「1つだけ」の結果を取得するためにPageable / Pageを作成する必要があります...使用するのは非常に不親切です。そして、あなたはSpring-Dataを担当しているようです。この問題をさらに詳しく調べていただければ幸いです:stackoverflow.com/questions/9276461/…。Spring-Dataのバグかどうか確認できますか?
smallufo

1
+これは機能しますが、感謝しますが、注釈ベースのソリューションは新しいバージョンの方が優れています
azerafati

1
カウントクエリがここで発生しますが、制限されたクエリが必要な場合はまったく不要です。
azerafati 2014

1
Listメソッドの戻り値の型として使用する場合はそうではありません。
Oliver Drotbohm 2014

3
キーワードはアノテーションを使用するメソッドには適用できないTopと思いますか?メソッド名ベースのクエリ生成を使用するものだけですか?First@Query
Ruslan Stelmachenko 2016年

106

Java 8とSpring Data 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
1つの結果に役立つ可能性がありますStream<User> ... {...} default Optional<User> ... { ...findAny() }
ゼノテラサイド2017

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

Spring Data 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
オプション<User> findFirstByLastnameOrderByIdDesc(String lastname);
krmanish007 2016年

トップ20の結果を取得した後、ページネーションを使用してWebサイトの次のページに移動すると、次の20の結果をどのように取得できますか?
kittu

@kittu、それはもちろん別の質問ですが、Pageableオブジェクトを渡す必要があります。春のドキュメントをチェックしてください
azerafati 2017

最初に指定されているのに、なぜメソッドがいまいましいリストを返すようにしたのですか?
Vasile Surdu

13

私にとって最良の選択はネイティブクエリです:

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

Hibernateで制限がサポートされているかどうか不明
Witold Kaczurba '28

2
コンセプト全体を壊します!代わりにEntityManagerを使用することをお勧めします!
Spektakulatius 2017

@ Code.IT KISSコンセプトを広めます。そのほかに、nativeQuery 無視しないために追加されたJPA アノテーションパラメータ。
Grigory Kislin 2017

@GKislinでは、findLimitOneByOtherObjのようなメソッドの名前を変更する必要があります。また、other_objが一意でない場合に間違った結果につながるOrderByを追加するのを忘れています。それ以外の場合、一意の列のwhereステートメントは制限なしで十分です
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>


クエリのwhere条件が2の場合、transactionRepository.findByFirstNameAndLastName(firstname、lastname)はどうなりますか?それは機能しますか?この例外org.springframework.data.mapping.PropertyReferenceExceptionが発生します。タイプボードのプロパティ作成が見つかりません。
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();

このコードをテストしましたが、機能しません。例外はありませんが、適切な結果がさらに必要になることはありません。また、ドキュメントはQueryHintsについて非常に薄いです。下記参照。 docs.spring.io/spring-data/jpa/docs/1.7.1.RELEASE/reference/...
bogdan.rusu

IIRC、クエリヒントが実行される保証はありませ。これは、「フレンドリーな推奨事項」を実装に渡すための単なる方法です。
Priidu Neemre 16

私はそれを試して@QueryHints({@QueryHint(name = org.hibernate.annotations.FETCH_SIZE, value = "1")})休止状態ではなく、別名:(動作しません
グリゴリーKislin

2
org.hibernate.annotations.FETCH_SIZEフェッチサイズ。制限なし、最大結果なし。ハイバーカント
Zhuravskiy Vitaliy

4

new PageRequest(0,10)新しいバージョンのSpringでは機能しません(私はを使用しています2.2.1.RELEASE)。基本的に、コンストラクターはSort型として追加のパラメーターを取得しました。さらに、コンストラクターはprotected、子クラスの1つを使用するか、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.