java - JPA 搜索字符串、长整型和布尔型
问题描述
我有一个 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
和过滤所有字段。
像这样的东西:
@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
and 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()
withLIKE
子句的提示吗?
解决方案
您是否考虑过规范的使用?
使用规范,您可以动态生成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);
}
首先,我们从添加name LIKE %text%
where 表达式的部分开始。
接下来,我们检查text
变量的值是否可以强制转换为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()
部分,以使搜索不区分大小写。
推荐阅读
- sql - 导入 csv excel 文件时,Laravel 7 时间戳迁移始终返回 0000-00-00 00:00:00
- react-native - React 本机构建过程失败
- tensorflow - rllib - 从检查点获取 TensorFlow 或 PyTorch 模型输出
- python-3.x - Sqlite3 选择查询返回空列表\无值
- python - 有没有办法使 datetime.datetime.now() 输出的时间成为 Windows 的有效参数?
- visual-studio-code - 硬件加速
- python - BS4 获取 python 中元素的完整 CSS 选择器
- ansible - Ansible:在配置文件中修改/添加多行的规范方法
- java - 是否可以将我的 64 位 JavaFX 应用程序移植到 32 位?
- image - 如何创建图像文件,其中图像的某些部分不会导致打印图像的打印机在该位置打印任何内容