Googleみたいにスペース区切りでAND検索したくて作ったやつ。
なおかつページングと照合順序(collate)も入れたかった。
例:「東京 銭湯」
参考
・setPrameterの参考
・ページスライスの参考
hibernate - Implementing Pagination using entity manager in spring - Stack Overflow
注意点
この実装だと半角カタカナの「プ」「ゲ」を全角カタカナ「プ」「ゲ」でLIKE検索するとヒットしない。
utf8_unicode_ciの仕様でそうなってしまう。
それも改善するならこっちもどうぞ↓
ポイント
ページスライス
クエリの生成。SOLが全て完成してから生成しないとダメ。
完成してから.setParameter()。
LIKE句をsetParameter()で渡すとこ。
ソース
// ここは検索メソッドとページングメソッドを呼び出してるだけ public Page<SkillEntity> searchBigSkill(String[] keywordArray, Pageable pageable) { List<SkillEntity> skillList = skillRepository.searchBigSkill(keywordArray); return commonService.returnPagedList(pageable, skillList); }
import org.springframework.data.domain.Page; import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; /** * ページスライス * * 受け取ったListをページにスライスする * * @param <E> * @param pageable * @param listOfEntities * @return 1ページ分にスライスされたListをpageableにして返す */ public <E> Page<E> returnPagedList(Pageable pageable, List<E> listOfEntities) { List<E> listToReturn = listOfEntities; if (pageable.isPaged()) { // 1ページのデータ数 int pageSize = pageable.getPageSize(); // 現在のページ番号 int currentPage = pageable.getPageNumber(); // 現在のページの最初の要素番号 int startItem = currentPage * pageSize; // ページに続きがあるかの判定 if (listOfEntities.size() < startItem) { //ページに続きがなければ空のリストを返す listToReturn = Collections.emptyList(); } else { //現在のページの最後の要素番号 int toIndex = Math.min(startItem + pageSize, listOfEntities.size()); // startItemからtoIndexまでのListを作る listToReturn = listOfEntities.subList(startItem, toIndex); } } return new PageImpl<>(listToReturn, pageable, listOfEntities.size()); }
import java.util.ArrayList; import java.util.List; import java.util.Objects; import javax.persistence.EntityManager; import javax.persistence.PersistenceContext; import javax.persistence.Query; import org.springframework.stereotype.Repository; public class Repository { @PersistenceContext private EntityManager em; //複数ワード検索&collate public List<SkillEntity> searchBigSkill(String[] keyWords) { String additionSQL = ""; // 追加するSQL。複数keywordの場合はAND句を追加 for (int i = 1; i < keyWords.length; i++) { additionSQL = additionSQL + " AND(bigName collate utf8_unicode_ci LIKE ?" + i + ")"; } // 元となるSQL String sql = "SELECT * FROM skill WHERE(bigName collate utf8_unicode_ci LIKE ?0)" + additionSQL + " ORDER BY bigID, normalID, smallID"; // クエリの生成。 Query query = em.createNativeQuery(sql, SkillEntity.class); // クエリに検索ワードをセット。 for (int i = 0; i < keyWords.length; i++) { query.setParameter(i, "%" + keyWords[i] + "%"); } @SuppressWarnings("unchecked") List<SkillEntity> skillList = query.getResultList(); return skillList; }