我想基于在我的searach 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和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);
}为了调用每个invoke parameters的方法,我手动使用ifs来检查哪些参数存在,哪些参数不存在(这让我在每次查看代码时都想哭)
有什么建议可以改进这一点,使其更有效率?请注意,需要包括JPA的分页。
发布于 2020-10-24 04:20:57
你的方法不是很好,因为你的存储库中有很多方法,它会随着时间的推移而增长,这在Spring.io中已经提到了,解决这个问题的更好的方法是使用Specification,你可以从JpaSpecificationExecutor扩展你的存储库,并传递从其他层执行的规范,它更干净,使你的代码易于阅读。甚至还有一种更好的方法,那就是querydsl,在这种方法中,你甚至不需要指定Specification,Spring data本身就可以为你处理许多情况。请阅读以下来自Spring本身的链接:advanced-spring-data-jpa-specifications-and-querydsl
发布于 2020-10-30 13:22:14
我已经开发了一个名为spring-dynamic-jpa的库,它使使用JPA实现动态查询变得更容易。
您可以使用它来编写查询模板。查询模板在执行之前将被构建到不同的查询字符串中,具体取决于调用该方法时的参数。
public interface InstituicaoRepository extends JpaRepository<Instituicao, Long> {
@DynamicQuery("select i from Instituicao i\n" +
"<@where>\n" +
" <#if cidadeId??>\n" +
" i.cidadeId = :cidadeId\n" +
" </#if>\n" +
" <#if nomeInstituicao??>\n" +
" and lower(i.nome) like lower(concat('%',:nomeInstituicao,'%'))\n" +
" </#if>\n" +
" <#if causaIds??>\n" +
" and i.causaId in :causaIds\n" +
" </#if>\n" +
"</@where>")
Page<Instituicao> findInstituicao(Long cidadeId, String nomeInstituicao, List<Long> causaIds, Pageable pageable);
}https://stackoverflow.com/questions/64505441
复制相似问题