目的
- 一覧検索画面に検索結果を表示する
- 検索条件は、入力されている項目は利用し、見入力の場合は無視してwhere句絞り込みを行う
前提
- FW : spring-boot
手順
repositoryの変更
- 検索対象であるRepositoryインターフェースで、JpaSpecificationExecutor を継承するように追加する
testRepository
@Repository
public interface TestRepository extends JpaRepository<TestEntity, Integer>, JpaSpecificationExecutor<TestEntity> {
}
- (補)リポジトリは、Entityをリストで管理するための仕組み
Specificationsクラスの用意
- 検索条件を作成する
- このメソッドが、一つの検索条件としてあとで使われる
- Specificationクラスは、where句で利用する検索条件の役割を果たす
testSpecifications
/**
* 案件区分が検索条件に存在する場合、where条件に加える
* @param anken_kbn
* @return
*/
public Specification<TestEntity> ankenKbnContains(String anken_kbn) {
if (Util.stringIsEmpty(anken_kbn))
return null;
else
return new Specification<TestEntity>() {
@Override
public Predicate toPredicate(Root<TestEntity> root, CriteriaQuery<?> query,
CriteriaBuilder cb) {
return cb.like(root.get("anken_kbn"), "%" + anken_kbn + "%");
}
};
}
- この部分は、anken_kbnという項目での部分一致検索を作成している
- andやorでチェーンして使う条件の分だけメソッドを用意する
- ここでは他にも
- Anken_name
- Rease_campany_name
で検索できるメソッドを用意している
- Specificationクラスで用意したメソッドがnullを返した場合は、無視されて検索が行われる、という動きをするため、
- 渡されたパラメータanken_kbn を、Util.stringIsEmpty(anken_kbn)で、anken_kbuが 空文字 である場合は null を返している
- 値が空でなかった 場合は、 検索条件 を作成してオブジェクトを返している。
DaoでSpecificationを利用し、検索を行う
- 検索条件をメソッドチェーンで設定することができる
- この時、先ほどのリポジトリが必要となるため、それがインジェクションできるところでこのメソッドを定義するか、または今回の場合は、コントローラにインジェクションされたリポジトリオブジェクトを第一引数にうけとって、それを利用している
- 第二引数のFormは画面上から受け渡された値を保持している。
- public List findBySearchItem(TestRepository testRepository,TestForm form
testDao
@Override
public List<TestEntity> findBySearchItem(TestRepository testRepository,TestForm form) {
TestSpecifications spec = new TestSpecifications();
List<TestEntity> result = TestRepository.findAll(Specifications.where(spec.ankenKbnContains(form.getAnken_kbn()))
.and(spec.ankenNameContains(form.getAnken_name()))
.and(spec.reaseCampanyNameContains(form.getRease_campany_name()))
);
System.out.println("検索結果");
System.out.println(result);
return result;
}
- repositoryインターフェースが用意しているfindAllメソッドのパラメータに検索条件となるオブジェクトを渡す
Specifications.where(spec.ankenKbnContains(form.getAnken_kbn()))
.and(spec.ankenNameContains(form.getAnken_name()))
.and(spec.reaseCampanyNameContains(form.getRease_campany_name()))
- 以上のように、and条件などで検索条件をチェーンにする
- specはspecificationsのオブジェクトで、そのクラスに作った先ほどのankenKbnContainsメソッドを使っている
- その次のformは、画面上から受け取った値を出している。それが検索条件の文字列となる
Controlerから利用する
- testListFormに、画面へ返すリストとして検索結果を入れる
- testDaoはインジェクションされている
- testRepositoryはインジェクションされている
- Daoを利用する。Daoで先ほどrepositoryクラスのインスタンスを必要としていたので、testRepositoryを渡している
testControleller
@RequestMapping("/search")
public ModelAndView search(@ModelAttribute("testListForm") TestListForm contractListForm,
ModelAndView mav) {
mav.setViewName("index");
Iterable<TestEntity> testEntityList = testDao.findBySearchItem(testRepository, testListForm);
System.out.println("検索結果");
System.out.println(tstEntityList);
mav.addObject("contractList", hdrEntityList);
mav.addObject("contractListF", new TestListForm());
return mav;
}
以上
- 手探りで可変where句を作成した
- 書き方としてこれがいい書き方なのか自身がない、もっと優れた書き方があるのかもしれない