java - 如何根据收到的参数使用 JPA 创建具有分页结果的自定义动态查询
问题描述
我想根据在我的搜索 API 端点中接收到的参数构建一个动态 JPA 查询,可能有 3 个参数:nome、cidade、causas(作为可以传递多个数字的数组):
@GetMapping("/search")
public ResponseEntity<?> findByNome(Pageable pageable,
@RequestParam Optional<String> nome,
@RequestParam Optional<Long[]> causas,
@RequestParam Optional<Long> cidade){
使用这 3 个参数,我需要使用 6 种可能的查询组合: *仅 cidade 通过 *cidade 和 causas *仅 nome *nome 和 causas *cidade 和 nome *cidade、nome 和 causas
为了达到同样的效果,我目前正在这样做:
@Repository
public interface InstituicaoRepository extends PagingAndSortingRepository<Instituicao, Long> {
//*only cidade passed
Page<Instituicao> findByCidadeId(long cidadeId, Pageable pageable);
//*cidade and causas
@Query("select i from Instituicao i where i.cidadeId = ?1 and i.causaId in (?2)")
Page<Instituicao> findByCidadeIdAndCausaIds(long cidadeId, Long[] causaIds, Pageable pageable);
//*only nome
Page<Instituicao> findByNomeContainingIgnoreCase(String nome, Pageable pageable);
//*nome and causas
@Query("select i from Instituicao i where lower(i.nome) like lower(concat('%',?1,'%')) and i.causaId in (?2)")
Page<Instituicao> findByNomeAndCausaIds(String nomeInstituicao, Long[] causaIds, Pageable pageable);
//*cidade and nome
@Query("select i from Instituicao i where i.cidadeId = ?1 and lower(i.nome) like lower(concat('%',?2,'%'))")
Page<Instituicao> findByCidadeIdAndNome(long cidadeId, String nomeInstituicao, Pageable pageable);
//*cidade, nome and causas
@Query("select i from Instituicao i where i.cidadeId = ?1 and lower(i.nome) like lower(concat('%',?2,'%')) and i.causaId in (?3)")
Page<Instituicao> findByCidadeIdAndNomeAndCausaIds(long cidadeId, String nomeInstituicao, Long[] causaIds, Pageable pageable);
}
调用每个 InstituicaoRepository 的方法然后我手动使用 ifs 来检查哪些参数存在和不存在(这让我每次看我的代码都想哭)
关于改进它以提高效率的任何建议?请注意,需要包含 JPA 的分页。
解决方案
你的方法不好,因为你的存储库中有很多方法,而且它会随着时间的推移而增长,它已经在 Spring.io 本身中提到,解决这个问题的更好方法是使用Specification
,你可以扩展你的存储库JpaSpecificationExecutor
并传递规范从其他层执行,它更干净,使您的代码易于阅读。还有一种更好的方法是 querydsl,您甚至不需要指定Specification
,Spring 数据本身可以为您处理许多情况。从 Spring 本身阅读以下链接:
advanced-spring-data-jpa-specifications-and-querydsl
推荐阅读
- macos - 微星机械键盘在 MacBook Pro 上输入错误
- python - 使用python获取图像中的最高点(z)
- python-3.x - tf.reduce_mean 在 tf.function 中不起作用
- asp.net-mvc - 如何在多个网站 OpenIdConnect Azure AD B2C 中登录用户?
- flutter - 错误:在此小部件 Flutter [PropertiesGrid] 上方找不到正确的提供程序
- tcp - 当 RMI TCP 连接打开时,Jmeter 测试停止?
- python - 阅读卡片上的文字
- html - 边距底部自动取决于视图高度
- python - 在Python中删除文本文件中的行时结合两个“for”来集成进度条?
- javascript - 总是设置状态(如果我转到上一个屏幕或转到下一个屏幕,我想总是将状态设置为成功)