Spring Data JPA - 创建动态查询注释

Posted

技术标签:

【中文标题】Spring Data JPA - 创建动态查询注释【英文标题】:Spring Data JPA - Create a dynamic Query annotation 【发布时间】:2020-12-28 09:47:16 【问题描述】:

我想知道是否可以将 @Query(value="") 替换为 @Query(value=query),其中 query 是我可以在某处编辑的字符串。

我必须创建一个函数来使用许多详细信息在我的数据库中进行搜索。

这里是我调用我的存储库的代码:

    public List<FilteringRuleEto> findRuleByParam(FilteringRuleDto filteringRule) 

        String Query = "SELECT rule FROM FilteringRuleEto rule WHERE";

        if (!filteringRule.getRouteClass().equals(null)) 
            Query += " rule.routeClass LIKE ?1 AND";
        
        if (!filteringRule.getCodeOperator().equals(null)) 
            Query += " rule.codeOperator LIKE ?2 AND";
        
        if (!filteringRule.getCommercialTrunk().equals(null)) 
            Query += " rule.commercialTrunk LIKE ?3 AND";
        
        if (!filteringRule.getSupportType().equals(null)) 
            Query += " rule.supportType LIKE ?4 AND";
        
        if (!filteringRule.getCalledNumber().equals(null)) 
            Query += " rule.calledNumber LIKE ?5 AND";
        
        if (!filteringRule.getCalledNumberRange().equals(null)) 
            Query += " rule.calledNumberRange = ?6 AND";
        
        if (!filteringRule.getCalledNumberWhitelist().equals(null)) 
            Query += " rule.calledNumberWhitelist = ?7 AND";
        
        if (!filteringRule.getCallingNumber().equals(null)) 
            Query += " rule.callingNumber LIKE ?8 AND";
        
        if (!filteringRule.getCallingNumberRange().equals(null)) 
            Query += " rule.callingNumberRange = ?9 AND";
        
        if (!filteringRule.getCallingNumberWhitelist().equals(null)) 
            Query += " rule.callingNumberWhitelist = ?10 AND";
        
        if (!filteringRule.getBeginDate().equals(null)) 
            Query += " rule.beginDate = ?11 AND";
        
        if (!filteringRule.getEndDate().equals(null)) 
            Query += " rule.endDate = ?12 AND";
        
        if (!filteringRule.getTgid().equals(null)) 
            Query += " rule.tgid LIKE ?13 AND";
        
        if (!filteringRule.getFilteringType().equals(null)) 
            Query += " rule.filteringType LIKE ?14 AND";
        
        if (!filteringRule.getDateInsert().equals(null)) 
            Query += " rule.dateInsert = ?15 AND";
        
        if (!filteringRule.getEndDate().equals(null)) 
            Query += " rule.dateUpdate = ?16 AND";
        
        if (!filteringRule.getComment().equals(null)) 
            Query += " rule.comment = ?17 AND";
        
        Query.substring(0, Query.length() - 3); 

        //Here I want to send the String Query to the Repository
        
        return this.filteringRuleRepository.findRuleByParameters(
                filteringRule.getRouteClass(),
                filteringRule.getCodeOperator(),
                filteringRule.getCommercialTrunk(),
                filteringRule.getSupportType(),
                filteringRule.getCalledNumber(),
                filteringRule.getCalledNumberRange(),
                filteringRule.getCalledNumberWhitelist(),
                filteringRule.getCallingNumber(),
                filteringRule.getCallingNumberRange(),
                filteringRule.getCallingNumberWhitelist(),
                filteringRule.getBeginDate(),
                filteringRule.getEndDate(),
                filteringRule.getTgid(),
                filteringRule.getFilteringType(),
                filteringRule.getDateInsert(),
                filteringRule.getDateUpdate(),
                filteringRule.getComment()
        );

    

在我的存储库中:

public interface FilteringRuleRepository extends JpaRepository<FilteringRuleEto, Integer> 

     
     @Query(value=theDynamicQuery)
     List<FilteringRuleEto> findRuleByParameters(String routeClass, String codeOperator, String commercialTrunk,
                                                 String supportType, String calledNumber, boolean calledNumberRange,
                                                 boolean calledNumberWhitelist, String callingNumber, boolean callingNumberRange,
                                                 boolean callingNumberWhitelist, OffsetDateTime beginDate, OffsetDateTime endDate,
                                                 String tgid, String filteringType, OffsetDateTime dateInsert, OffsetDateTime dateUpdate,
                                                 String comment);


目标是使搜索尽可能快。当用户想要在数据库中搜索只有 2 个参数时,我不想使用具有 17 个参数的查询。

我按照这个网站编写了我的代码: https://www.baeldung.com/spring-data-jpa-query

但我认为第 9 部分不是我想要的。或者我理解错了。

感谢阅读。

【问题讨论】:

使用这样的代码会破坏很多编写好的代码原则。此外,spring 不支持动态查询。您可以在 JPA 中使用 Criteria API。例如,您可以编写一个需要映射或必要参数列表的方法,并基于这些参数构建您的查询。还有一些流行的方法来进行动态查询,例如 QueryDSL 和 JPA Specifications。 @AndriiSyd QueryDSL 看起来就像我正在寻找的一样。我暂时就这样搜索。 【参考方案1】:

我开发了一个名为 spring-dynamic-jpa 的库,以便更轻松地使用 JPA 实现动态查询。

您可以使用它来编写查询模板。查询模板在执行前会根据你调用方法时的参数,构建成不同的查询字符串。

public interface FilteringRuleRepository extends JpaRepository<FilteringRuleEto, Integer> 
    @DynamicQuery("select t from FilteringRuleEto t\n" +
        "<@where>\n" +
        "  <#if routeClass?has_content>\n" +
        "    and t.routeClass like :routeClass\n" +
        "  </#if>\n" +
        "  <#if codeOperator?has_content>\n" +
        "    and t.codeOperator like :codeOperator\n" +
        "  </#if>\n" +
        "  <#if commercialTrunk?has_content>\n" +
        "    and t.commercialTrunk like :commercialTrunk\n" +
        "  </#if>\n" +
        "</@where>"
    )
    List<FilteringRuleEto> findRuleByParameters(String routeClass, String codeOperator, String commercialTrunk,
                                                String supportType, String calledNumber, boolean calledNumberRange,
                                                boolean calledNumberWhitelist, String callingNumber, boolean callingNumberRange,
                                                boolean callingNumberWhitelist, OffsetDateTime beginDate, OffsetDateTime endDate,
                                                String tgid, String filteringType, OffsetDateTime dateInsert, OffsetDateTime dateUpdate,
                                                String comment);

【讨论】:

非常感谢!这正是我正在寻找的。我不得不问我是否可以在我的项目中使用它,但它看起来像是一个很好的答案。 是的,你可以在你的项目中使用它。

以上是关于Spring Data JPA - 创建动态查询注释的主要内容,如果未能解决你的问题,请参考以下文章

Spring-Data-JPA 中的查询如何动态组装条件?

Spring Data JPA:创建规范查询获取连接

spring Data jpa 一对多关联 动态查询怎么写

spring data jpa 动态查询(mysql)

spring data jpa 动态查询(mysql)

请教关于Spring Data JPA动态查询参数的问题