Поиск по комбинации нескольких параметров через собственный запрос - PullRequest
0 голосов
/ 07 сентября 2018

В настоящее время я работаю над функционалом, который позволит системе осуществлять поиск квитанций общедоступных сервисов по комбинации из 6 параметров, которые могут иметь значение null, что означает, что квитанции не должны фильтроваться этим параметром: 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);

}

Мое рассуждение состояло в том, что, если параметр был нулевым, это означало, что тот, кто использовал Web-сервис, не заинтересован в этом параметре, поэтому, если это произойдет, я задаю эту переменную в качестве имени столбца, чтобы она не влияла в предложении WHERE и в теория упростила его, но я обнаружил, что он будет посылать имена в виде строк, так что он не будет распознаваться как выражение sql, что является недостатком моего мышления, и, как я сказал, должен быть другой способ, кроме написания каждого метода для каждой комбинации, я ценю любую помощь:).

Ответы [ 2 ]

0 голосов
/ 11 сентября 2018

Я нашел способ исправить это, я сделал это так (я собираюсь показать только собственный Query, так как это внутренняя вещь, которую я изменил):

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» (если его не следует использовать для фильтрации данных) или фактического значения, для меня это работало нормально!

0 голосов
/ 11 сентября 2018

Вы должны использовать 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();
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...