Postgres和JPA命名查询-WHERE中的任何(*)值

时间:2019-06-09 09:24:36

标签: java postgresql jpa orm named-query

我想为某些特定的GET情况编写过滤器查询。

我现在正在做的是针对每种情况编写单独的查询,这非常耗时。相反,我想编写一个大的命名查询,如果设置了过滤器,则可以在其中将值放入WHERE子句中,否则可以输入ANY。 JPA有可能吗? 这是一个示例控制器,它通过特定的客户ID返回付款:

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 个答案:

答案 0 :(得分:2)

您可以尝试更改查询,例如:

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

注意:我认为JPA中的引用深达2个级别,这里有3个级别:

i.clientContractData.client.id

您可能需要在此处使用额外的显式连接

答案 1 :(得分:0)

更新的查询

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为null,则发送null值:

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

对于更复杂的情况,您可以使用rsql-jpa-specification项目:

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