[英]JPA search String, Long and Boolean
我有一個 Spring-Boot 應用程序。 有一個實體:
@Entity
@Table(name = "user")
public class User {
private Long id;
private String name;
private Long schoolId;
private Boolean isActive;
// getters and setters
}
我有一個存儲庫:
@Repository
public interface UserRepositoryPageable extends PagingAndSortingRepository<User, Long> {
}
我需要請求按schoolId
進行搜索schoolId
某個字符串過濾所有字段。
像這樣的東西:
@Query("SELECT u FROM User u " +
"WHERE u.schoolId = :schoolId AND (" +
"u.id like %:searchVal% OR " +
"u.name like %:searchVal% OR " +
"u.isActive like %:searchVal%)")
Page<User> getUserBySchoolIdWithFilter(@Param("schoolId") Long schoolId,
Pageable pageable,
@Param("searchVal") String searchVal);
但是我收到一個異常,因為我嘗試將like
應用到Long
和Boolean
。
例如,如果我嘗試按“testSearchValue”進行過濾,則會收到以下異常:
java.lang.IllegalArgumentException: 參數值 [%testSearchValue%] 與預期類型 [java.lang.Long (n/a) 不匹配
不幸的是, CAST
和CONVERT
對我不起作用。
那么有什么解決方法嗎?
一些細節
我向這個 API 發送了一個GET
請求:
@RequestMapping(path = "users/{schoolId}/search", method = GET)
public ResponseEntity<Page<User>> searchUserBySchoolWithFilter(
@PathVariable(value = "schoolId") Long schoolId, Pageable pageable,
@RequestParam(value = "searchVal", required = false) String searchVal) {
return new ResponseEntity<>(userService
.getUserBySchoolIdWithFilter(schoolId, pageable, searchVal), HttpStatus.OK);
}
然后在UserService
:
public Page<User> getUserBySchoolIdWithFilter(Long schoolId, Pageable pageable, String searchVal) {
return userRepositoryPageable.getUserBySchoolIdWithFilter(schoolId, pageable, searchVal);
}
所以:
在我看來,問題的基本點是將Long
和Boolean
表示為String
。
也許最好使用nativeQuery
? 如果是這樣,那么您能否給我一個關於如何將CAST()
或CONVERT()
與LIKE
子句一起使用的提示?
您是否考慮過Specifications的用法?
使用規范,您可以動態生成 spring 數據查詢的WHERE
部分。 為了在 Spring 數據 JPA 查詢中使用規范,您必須擴展org.springframework.data.jpa.repository.JpaSpecificationExecutor
接口。 因此,您的用戶存儲庫可能如下所示:
public interface UserRepository extends JpaRepository<User, Long>, JpaSpecificationExecutor<User> {
}
您的搜索方法可能如下所示
public List<User> getAllFilterByString(String text) {
if(StringUtils.isEmpty(text))
return userRepository.findAll();
Specification<User> specification =
(root, query, cb) -> {
List<Predicate> predicates = new ArrayList<>();
predicates.add(cb.like(cb.lower(root.get("name")), "%"+text.toLowerCase()+"%"));
//check if the text value can be casted to long.
//if it is possible, then add the check to the query
try {
long longValue = Long.valueOf(text);
predicates.add(cb.equal(root.get("id"), longValue));
}
catch (NumberFormatException e) {
//do nothing, the text is not long
}
//check if the text can be casted to boolean
//if it is possible, then add the check to the query
Boolean value = "true".equalsIgnoreCase(text) ? Boolean.TRUE :
"false".equalsIgnoreCase(text) ? Boolean.FALSE : null;
if(value != null) {
predicates.add(cb.equal(root.get("isActive"), value));
}
return cb.or(predicates.toArray(new Predicate[] {}));
};
return userRepository.findAll(specification);
}
首先,我們開始在 where 表達式中添加name LIKE %text%
部分。
接下來,我們檢查text
變量的值是否可以轉換為long
。 如果可以,那么我們從字符串中取出 long 值並將其添加到 where 查詢中。
最后我們檢查text
變量是否可以轉換為布爾值。 如果可以,那么我們也將該檢查添加到查詢中。
例如,如果text
變量的值是test1,則 where 部分將是
WHERE name LIKE '%test1%;
如果text
變量的值為真,則 where 部分將是
WHERE name LIKE '%true%' OR is_active = true;
最后,如果text
變量的值為12,那么 where 部分將是
WHERE name LIKE '%12%' OR id = 12;
注意:當我們按名稱搜索時,我將cb.lower(root.get("name"))
和text.toLowerCase()
到部分,以使搜索不區分大小寫。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.