【Java】Specificationでデータ取得を行う
初めまして、福岡事業所のKOHEIと申します。
データベースから取得する際、Specificationやカスタムクエリの存在が欠かせません。
1つや2つのみの検索条件だとカスタムクエリで楽に取得出来るのですが、大規模な開発で多数の検索条件が絡んでくるとカスタムクエリとは言えない・・・
そのような時はSpecificationを使い、Java側で検索条件を指定することでスタイリッシュにデータを取得することができます。(SQLのWHERE句のようなもの)
今回は私が業務でよく使用するSpecificationをまとめてみました。
もし間違い等ございましたら、ご指摘いただけると幸いです。
前提としてUserテーブル構成はこのようなものをイメージしていただければと思います。
一致条件
・Userテーブルに存在するカラム「from_name」が"福岡"のもののみ取得する条件
Specification<User> fromNameEquals =
(root, query, cb) -> cb.equal(root.get(fromName), "福岡");
不一致条件
・Userテーブルに存在するカラム「from_name」が"福岡"に一致しないもののみ取得する条件
Specification<User> fromNameNotEquals =
(root, query, cb) -> cb.notEqual(root.get(fromName), "福岡");
Null一致条件
・Userテーブルに存在するカラム「from_name」がnullのもののみ取得する条件
Specification<User> fromNameIsNull =
(root, query, cb) -> cb.isNull(root.get(fromName));
Null不一致条件
・Userテーブルに存在するカラム「from_name」がnullではないもののみ取得する条件
Specification<User> fromNameIsNotNull =
(root, query, cb) -> cb.isNotNull(root.get(fromName));
~より大きい条件
・Userテーブルに存在するカラム「time」が第2引数よりも大きいもののみ取得する条件
Specification<User> timeGreaterThan =
(root, query, cb) -> cb.greaterThan(root.get(time), ZonedDateTime.now());
~より小さい条件
・Userテーブルに存在するカラム「time」が第2引数よりも小さいもののみ取得する条件
Specification<User> timeLessThan =
(root, query, cb) -> cb.lessThan(root.get(time), ZonedDateTime.now());
~より大きいまたは等しい条件
・Userテーブルに存在するカラム「time」が第2引数よりも大きいもの、もしくは等しいもののみ取得する条件
Specification<User> timeGreaterThanOrEqualTo =
(root, query, cb) -> cb.greaterThanOrEqualTo(root.get(time), ZonedDateTime.now());
~より小さいまたは等しい条件
・Userテーブルに存在するカラム「time」が第2引数よりも小さいもの、もしくは等しいもののみ取得する条件
Specification<User> timeLessThanOrEqualTo =
(root, query, cb) -> cb.lessThanOrEqualTo(root.get(time), ZonedDateTime.now());
第2引数と第3引数の間に位置するもののみ取得する条件
・Userテーブルに存在するカラム「time」がカラム「start_date」とカラム「end_date」の間に位置するもののみ取得する条件
Specification<User> timeBetween =
(root, query, cb) -> cb.between(cb.literal(time), root.get(startDate), root.get(endDate));
Listに含まれているか
・Userテーブルに存在するカラム「from_name」の値がfromNameListに含まれているもののみ取得する条件
Specification<User> fromNameInList =
(root, query, cb) -> root.get(fromName).in(fromNameList);
これらを組み合わせることで複数の条件を定義した状態でデータを取得することができます。
・取得例
public List<User> getFromFukuoka () {
return repository.findAll(fromNameNotEquals.and(fromNameIsNotNull));
}
上記の条件であれば「from_name」が"福岡"ではないもの、かつ「from_name」がnullでないものを取得する条件となっていますので、佐藤さんと田島さんのデータを取得することになります。
今回は条件を2つしか指定していませんが、基本的な流れはこういったものだと思っていただければと思います。
以上、私が業務でよく使用するSpecificationについてまとめてみました。
必要なデータのみを取得し、メモリの無駄遣いを防ぐためにもカスタムクエリやSpecificationは欠かせない存在だと感じています。
私自身、まだまだ分からないことも多く業務中に悩むこともありましたので、一度まとめてみるのが良いのではと思い投稿させていただきました。これからも学ぶ姿勢は忘れずに取り組んでいこうと思います。
また時間があるときにまとめていこうと思います。
ALHについて知る
↓ ↓ ↓ 採用サイトはこちら ↓ ↓ ↓
↓ ↓ ↓ コーポレートサイトはこちら ↓ ↓ ↓
↓ ↓ ↓ もっとALHについて知りたい? ↓ ↓ ↓