Postgres 和 JPA 命名查询 - WHERE 中的任何 (*) 值
Postgres & JPA named queries - any (*) value in WHERE
我想为某些特定的 GET 案例编写过滤器查询。
我现在正在为每个案例编写单独的查询,这非常耗时。相反,我想编写一个大的命名查询,如果设置了过滤器,我可以在其中将一个值放入 WHERE 子句,否则任何。 JPA可以吗?
这是一个示例控制器,它 returns 通过特定客户端 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
来执行此操作。
您可以尝试像这样更改您的查询:
WHERE (i.clientContractData.client.id = :clientId or :clientId = -1)
注意:我认为 JPA 中的引用深达 2 层,这里有 3 层:
i.clientContractData.client.id
您可能需要在此处使用额外的显式连接
更新查询,
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-specification 项目来处理更复杂的情况:
我想为某些特定的 GET 案例编写过滤器查询。
我现在正在为每个案例编写单独的查询,这非常耗时。相反,我想编写一个大的命名查询,如果设置了过滤器,我可以在其中将一个值放入 WHERE 子句,否则任何。 JPA可以吗? 这是一个示例控制器,它 returns 通过特定客户端 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
来执行此操作。
您可以尝试像这样更改您的查询:
WHERE (i.clientContractData.client.id = :clientId or :clientId = -1)
注意:我认为 JPA 中的引用深达 2 层,这里有 3 层:
i.clientContractData.client.id
您可能需要在此处使用额外的显式连接
更新查询,
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-specification 项目来处理更复杂的情况: