JPAおよびSpring Data JPAを使用したクエリ結果の制限
1. 前書き
このチュートリアルでは、JPAとSpring Data JPAを使用してlearn about limiting query resultsに移動します。
まず、クエリを実行するテーブルと、再現するSQLクエリを確認します。
次に、JPAとSpring DataJPAを使用してそれを実現する方法について詳しく説明します。
始めましょう!
2. テストデータ
以下に、この記事全体でクエリを実行する表を示します。
答えたい質問は、「最初に占有された座席は何で、誰が占有しているのですか?」です。
ファーストネーム |
苗字 |
座席番号 |
Jill |
スミス |
50 |
Eve |
ジャクソン |
94 |
Fred |
Bloggs |
22 |
リッキ |
ボビー |
36 |
Siya |
コリシ |
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 findOrderedBySeatNumberLimitedTo(int limit) {
return entityManager.createQuery("SELECT p FROM Passenger p ORDER BY p.seatNumber",
Passenger.class).setMaxResults(limit).getResultList();
}
}
リポジトリメソッドでは、EntityManagerを使用してQueryを作成し、その上でsetMaxResults()メソッドを呼び出します。
この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. Spring Data JPAを使用
Spring Data JPAを使用してSQLを生成することもできます。
5.1. firstまたはtop
これにアプローチする1つの方法は、キーワードfirstまたはtop.でメソッド名の派生を使用することです。
必要に応じて、返される結果の最大サイズとして数値を指定できます。 省略すると、Spring Data JPAは結果サイズを1と想定します。
最初に占有された座席が何で、誰が占有しているかを知りたいことを思い出して、次の2つの方法で番号を省略して取得できます。
Passenger findFirstByOrderBySeatNumberAsc();
Passenger findTopByOrderBySeatNumberAsc();
上記のように、インスタンスの結果を1つに制限する場合は、Optionalを使用して結果をラップすることもできます。
Optional findFirstByOrderBySeatNumberAsc();
Optional findTopByOrderBySeatNumberAsc();
5.2. Pageable
または、Pageableオブジェクトを使用することもできます。
Page page = repository.findAll(PageRequest.of(0, 1, Sort.by(Sort.Direction.ASC, "seatNumber")));
JpaRepository,のデフォルトの実装を見ると、SimpleJpaRepository, はQuery#setMaxResultsも呼び出していることがわかります。
protected 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. 比較
これらの選択肢はどちらも、後の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 ?
first とtopは規則を優先し、Pageableは構成を優先します。
6. 結論
代わりに、Query#maxResultsに対して単一のメソッド呼び出しを行うか、Spring Data JPAメソッド名にキーワードfirstまたはtopを含めます。
いつものように、コードover on GitHubを見つけることができます。