Именованные запросы Postgres & JPA - любое (*) значение в WHERE - PullRequest
0 голосов
/ 09 июня 2019

Я хочу написать фильтр запросов для некоторых конкретных случаев GET.

То, что я сейчас делаю, - это написание отдельных запросов для каждого случая, что отнимает много времени. Вместо этого я хотел бы написать один большой именованный запрос, где я могу либо поместить значение в предложение WHERE, если установлен фильтр, в противном случае - ЛЮБОЙ. Это возможно с JPA? Это пример контроллера, который возвращает платежи по определенному идентификатору клиента:

public List<PaymentEntity> findAllByClientId(final int page, final int pageSize, final String fromDate,
        final String toDate, final Long clientId) {
    Map<String, Object> parameters = new HashMap<>();
    parameters.put("clientId", clientId);
    return super.findWithNamedQueryPagination("PaymentEntity.findAllWithPaginationByClientId", parameters,
            PaymentEntity.class, page, pageSize, fromDate, toDate);
}

И это принадлежащий именованный запрос:

SELECT i FROM PaymentEntity i WHERE i.clientContractData.client.id = :clientId AND i.createdAt BETWEEN :fromDate AND :toDate ORDER BY i.createdAt DESC

Теперь мне хотелось бы передать такой параметр:

    if(clientId == null) {
        parameters.put("clientId", "*");
    } else {
        parameters.put("clientId", clientId);
    }

Но теперь, конечно, я получаю ошибку типа: Parameter value [*] did not match expected type [java.lang.Long (n/a)]

Каков наилучший способ сделать это? Нужно ли писать собственные запросы или есть способ с именованными запросами?

Изменить, чтобы уточнить: В приведенном выше примере показан запрос с типом Long, но мне нужно сделать это и с String.

Ответы [ 2 ]

2 голосов
/ 09 июня 2019

Вы можете попытаться изменить свой запрос следующим образом:

WHERE (i.clientContractData.client.id = :clientId or :clientId = -1)

Примечание: я думаю, что ссылки в JPA доходят до 2 уровней, и здесь у вас есть 3 уровня:

i.clientContractData.client.id

здесь вам может понадобиться дополнительное явное соединение

0 голосов
/ 09 июня 2019

Обновленный запрос,

SELECT i FROM PaymentEntity i WHERE 
       ((i.clientContractData.client.id = :clientId and :clientId IS NOT NULL) 
        or (i.clientContractData.client.id IS NOT NULL AND :clientId IS NULL)) 
         AND i.createdAt BETWEEN :fromDate AND :toDate ORDER BY i.createdAt DESC

Отправка нулевого значения, если clientId равен нулю:

if(clientId == null) {
    parameters.put("clientId", null);
} else {
    parameters.put("clientId", clientId);
}

Вы используете проект спецификации rsql-jpa для более сложных случаев:

https://github.com/perplexhub/rsql-jpa-specification

...