【问题标题】:Search by the combination of multiple parameters via Native Query通过 Native Query 组合多个参数进行搜索
【发布时间】:2019-02-13 05:18:33
【问题描述】:

我目前正在开发一个功能,该功能将允许系统通过 6 个参数的组合来搜索公共服务收据,这些参数可以为空,这意味着收据不应被此参数过滤:accountNumber、amountRangeMin、amountRangeMax、dateRangeMin , dateRangeMax, publicServiceId。然而,为每个参数组合创建一个方法不是一种选择,我认为必须有更好的方法,起初我的方法如下:

在我的服务中,我有这个方法:

public Map<String,Object> findPublicServiceReceiptsByParams(Integer accountNumber, BigDecimal amountRangeMin,
        BigDecimal amountRangeMax, LocalDate dateRangeMin, LocalDate dateRangeMax, Integer publicServiceId) {
    Map<String,Object> publicServiceReceipts = new HashMap<String,Object>();
    String accountNumberFilter = !(accountNumber==null) ? accountNumber.toString() : "AccountNumberTableName";
    String amountRangeMinFilter = !(amountRangeMin==null) ? amountRangeMin.toString() : "table.AmountColumnName";
    String amountRangeMaxFilter = !(amountRangeMax==null) ? amountRangeMax.toString() : "table.AmountColumnName";
    String dateRangeMinFilter = !(dateRangeMin==null) ? dateRangeMin.toString() : "Table.ReceiptCreationDateColumn";
    String dateRangeMaxFilter = !(dateRangeMax==null) ? dateRangeMax.toString() : "Table.ReceiptCreationDateColumn";
    String publicServiceIdFilter = !(publicServiceId==null) ? publicServiceId.toString() : "table.publicServiceIdColumn";
    publicServiceReceipts = publicServiceReceiptRepository.findPublicServiceReceiptsByParams(accountNumberFilter,
            amountRangeMinFilter, amountRangeMaxFilter, dateRangeMinFilter, dateRangeMaxFilter,
            publicServiceIdFilter);
    return publicServiceReceipts;
}

然后在我的存储库中我有:

final static String FIND_PUBLIC_SERVICES_BY_ARGS = "Select (Insert whatever logic should go in here to select columns from receipts the where clause is the one that matters)"
        + "    WHERE ACT.ACT_AccountNumber=:accountNumberFilter\n"
        + "      AND PSE.PSE_Id=:publicServiceIdFilter\n"
        + "      AND PSR.PSR_CreateDate BETWEEN :dateRangeMinFilter AND :dateRangeMaxFilter\n"
        + "      AND PSR.PSR_Amount BETWEEN :amountRangeMinFilter AND :amountRangeMaxFilter\n"
        + " order by PSR.PSR_CreateDate desc";

@Query(nativeQuery = true, value = FIND_PUBLIC_SERVICES_BY_ARGS)
Map<String, Object> findPublicServiceReceiptsByParams(@Param("accountNumberFilter") String accountNumberFilter,
        @Param("amountRangeMinFilter") String amountRangeMinFilter,
        @Param("amountRangeMaxFilter") String amountRangeMaxFilter,
        @Param("dateRangeMinFilter") String dateRangeMinFilter,
        @Param("dateRangeMaxFilter") String dateRangeMaxFilter,
        @Param("publicServiceIdFilter") String publicServiceIdFilter);

}

我的理由是,如果参数为 null 意味着使用 Web 服务的人对该参数不感兴趣,所以如果发生这种情况,我将该变量设置为列名称,这样它就不会影响 WHERE 子句和理论使它更简单,但我发现它会将名称作为字符串发送,因此它不会被识别为 sql 语句,这是我思维中的缺陷,正如我所说,除了编写每种方法之外,必须有另一种方法对于每种组合,我都感谢您的帮助:)。

【问题讨论】:

    标签: java jpa nativequery


    【解决方案1】:

    我找到了解决这个问题的方法,我是这样做的(我将只显示本机查询,因为它是我唯一改变的东西):

    DECLARE  @actNum varchar(50),@crdNum varchar(50),@pseId varchar(50),@dateMin varchar(50),@dateMax varchar(50),@amountMin varchar(50),@amountMax varchar(50)
    SET @actNum = :actNum
    SET @crdNum = :crdNum 
    SET @pseId =  :pseId 
    SET @dateMin = :dateMin 
    SET @dateMax = :dateMax 
    SET @amountMin = :amountMin 
    SET @amountMax = :amountMax 
    --Whatever Select with joins statement
                       WHERE ACT.ACT_AccountNumber = CASE WHEN @actNum = 'N/A' 
                                                 THEN ACT.ACT_AccountNumber 
                                                 ELSE @actNum END
                     AND CRD_CardNumber = CASE WHEN @crdNum = 'N/A' 
                                          THEN CRD_CardNumber 
                                          ELSE @crdNum END
                     AND PSE.PSE_Id= CASE WHEN @pseId = 'N/A' 
                                     THEN PSE.PSE_Id 
                                     ELSE @pseId END
                     AND PSR.PSR_CreateDate >= CASE WHEN @dateMin = 'N/A' 
                                                    THEN PSR.PSR_CreateDate 
                                                    ELSE @dateMin END 
                                            AND PSR.PSR_CreateDate <= CASE WHEN @dateMax = 'N/A' 
                                                THEN PSR.PSR_CreateDate 
                                                ELSE @dateMax END
                     AND PSR.PSR_Amount BETWEEN CASE WHEN @amountMin = 'N/A' 
                                                THEN PSR.PSR_Amount 
                                                ELSE @amountMin END 
                                        AND CASE WHEN @amountMax = 'N/A' 
                                            THEN PSR.PSR_Amount 
                                            ELSE @amountMax END 
                ORDER BY PSR.PSR_CreateDate DESC
    

    后端会将参数作为“N/A”(如果不应该用于过滤数据)或实际值发送,这对我来说很好!

    【讨论】:

    • 这段代码的问题是,如果逻辑变得更复杂,它可能会变得难以维护。此外,调用此方法的人必须知道发送值“N/A”,如果它不包含在查询中。简单地省略该值会更容易理解。我不知道是否有任何性能差异,你必须衡量这一点。但是,如果代码适用于您的情况,它不会变得更复杂,并且与您的代码交互的人数不会太多,您可以保持原样。
    【解决方案2】:

    您应该使用Criteria API,它专为创建动态查询而设计。在这种情况下,命名查询并不是真的要使用。 有了它,您可以执行以下操作:

    @PersistenceContext
    EntityManager em;
    
    List<YourEntity> method(String argument) {
        CriteriaBuilder cb = em.getCriteriaBuilder();
        CriteriaQuery<YourEntity> cq = cb.createQuery(YourEntity.class);
        Root<YourEntity> root = cq.from(YourEntity.class);
    
        List<Predicate> predicates = new ArrayList<>();
        if (argument == null) {
            predicates.add(cb.equal(root.get("yourAttribute"), argument);
        }
        // rest of your logic goes here
    
        cq.where(predicates.toArray(new Predicate[]{}));
        return em.createQuery(cq).getResultList();
    }
    

    【讨论】:

    • 听起来不错,谢谢!但是,由于似乎没有人回答我找到了一种解决方法来解决您的方法 idk 如果它是一个更好的方法,我不这么认为,因为您的方法看起来很干净,我将添加我的方法并回答这个问题,这样您就可以检查出来并给我一些反馈,无论如何谢谢你的回答我什至不知道 API 存在,它似乎很有用
    猜你喜欢
    • 2011-11-05
    • 1970-01-01
    • 2019-05-21
    • 2013-05-05
    • 2018-04-13
    • 2016-05-21
    • 1970-01-01
    • 1970-01-01
    • 2020-05-20
    相关资源
    最近更新 更多