JPAおよびSpringDataJPAによるクエリ結果の制限
1. 序章
このチュートリアルでは、クエリ結果の制限についてJPAおよびSpring DataJPAで学習します。
まず、クエリするテーブルと、再現するSQLクエリを確認します。
次に、JPAとSpring DataJPAを使用してそれを実現する方法について詳しく説明します。
始めましょう!
2. テストデータ
以下に、この記事全体でクエリを実行するテーブルを示します。
私たちが答えたい質問は、「最初に占有された座席は何で、誰がそれを占有しているのか」です。
ファーストネーム | 苗字 | 座席番号 |
---|---|---|
ジル | スミス | 50 |
イブ | ジャクソン | 94 |
フレッド | Bloggs | 22 |
リッキ | ボビー | 36 |
シヤ | コリシ | 85 |
3. SQL
SQLを使用すると、次のようなクエリを作成できます。
SELECT firstName, lastName, seatNumber FROM passengers ORDER BY seatNumber LIMIT 1;
4. JPAセットアップ
JPAでは、テーブルをマップするために最初にエンティティが必要です。
@Entity
class Passenger {
@Id
@GeneratedValue
@Column(nullable = false)
private Long id;
@Basic(optional = false)
@Column(nullable = false)
private String fistName;
@Basic(optional = false)
@Column(nullable = false)
private String lastName;
@Basic(optional = false)
@Column(nullable = false)
private int seatNumber;
// constructor, getters etc.
}
次に、クエリコードをカプセル化するメソッドが必要です。ここでは PassengerRepositoryImpl#findOrderedBySeatNumberLimitedTo(int limit)として実装されています。
@Repository
class PassengerRepositoryImpl {
@PersistenceContext
private EntityManager entityManager;
@Override
public List<Passenger> findOrderedBySeatNumberLimitedTo(int limit) {
return entityManager.createQuery("SELECT p FROM Passenger p ORDER BY p.seatNumber",
Passenger.class).setMaxResults(limit).getResultList();
}
}
リポジトリメソッドでは、 EntityManager を使用して、 setMaxResults()メソッドを呼び出すQueryを作成します。
このQuery#setMaxResults の呼び出しにより、最終的に、生成されたSQLにlimitステートメントが追加されます。
select
passenger0_.id as id1_15_,
passenger0_.fist_name as fist_nam2_15_,
passenger0_.last_name as last_nam3_15_,
passenger0_.seat_number as seat_num4_15_
from passenger passenger0_ order by passenger0_.seat_number limit ?
5. SpringDataJPAを使用
SpringDataJPAを使用してSQLを生成することもできます。
5.1. 最初のまたはトップ
これにアプローチする1つの方法は、キーワードfirstまたはtop。でメソッド名の派生を使用することです。
オプションで、返される最大結果サイズとして数値を指定できます。 これを省略すると、SpringDataJPAは結果サイズを1と見なします。
どちらが最初に占有され、誰が占有しているかを知りたいので、次の2つの方法で番号を省略して取得できます。
Passenger findFirstByOrderBySeatNumberAsc();
Passenger findTopByOrderBySeatNumberAsc();
上記のように、インスタンスの結果を1つに制限する場合は、オプションを使用して結果をラップすることもできます。
Optional<Passenger> findFirstByOrderBySeatNumberAsc();
Optional<Passenger> findTopByOrderBySeatNumberAsc();
5.2. ページング可能
または、Pageableオブジェクトを使用することもできます。
Page<Passenger> page = repository.findAll(
PageRequest.of(0, 1, Sort.by(Sort.Direction.ASC, "seatNumber")));
JpaRepository、 SimpleJpaRepository、のデフォルトの実装を見ると、 Query#setMaxResultsも呼び出されていることがわかります。
protected <S extends T > Page < S > readPage(TypedQuery < S > query,
Class < S > domainClass, Pageable pageable,
@Nullable Specification < S > spec) {
if (pageable.isPaged()) {
query.setFirstResult((int) pageable.getOffset());
query.setMaxResults(pageable.getPageSize());
}
return PageableExecutionUtils.getPage(query.getResultList(), pageable, () -> {
return executeCountQuery(this.getCountQuery(spec, domainClass));
});
}
5.3. 比較
これらの選択肢はどちらも、最初のと top が規則を優先し、Pageableが構成を優先するという目的のSQLを生成します。
select
passenger0_.id as id1_15_,
passenger0_.fist_name as fist_nam2_15_,
passenger0_.last_name as last_nam3_15_,
passenger0_.seat_number as seat_num4_15_
from passenger passenger0_ order by passenger0_.seat_number asc limit ?
6. 結論
JPA でクエリ結果を制限することは、SQLとは少し異なります。 JPQLにlimitキーワードを直接含めません。
代わりに、 Query#maxResults を1回呼び出すか、キーワードfirstまたはtopをSpring DataJPAに含めます。 ]メソッド名。
いつものように、コードはGitHubでから入手できます。