将数组参数绑定到本机查询

2022-09-04 20:36:30

我有以下列的表product_spec_entry

  • product_spec_id
  • commodity_spec_id

对于一个product_spec_id可能是几个commodity_spec_id,例如:

|product_spec_id | commodity_spec_id|
|----------------|------------------|
|1683            |1681              |
|1692            |1693              |
|1692            |1681              |
|1692            |1687              |
|1692            |1864              |
|1860            |1681              |
|1868            |1681              |
|1868            |1864              |

我想获取所有commodity_spec_id都作为参数传递的所有product_spec_id

我写了下一个查询:

SELECT ps.product_spec_id, commodities
FROM (
       SELECT
         product_spec_id,
         array_agg(commodity_spec_id) AS commodities
       FROM system.product_spec_entry
       GROUP BY product_spec_id) ps
WHERE Cast(ARRAY [1681, 1864] as BIGINT[]) <@ Cast(ps.commodities as BIGINT[]);

它工作正常,并返回预期的结果:

product_spec_id = 1692, 1868

我尝试将此查询用于JPA本机查询:

String query = "SELECT ps.product_spec_id " +
                "FROM ( " +
                "       SELECT " +
                "         product_spec_id, " +
                "         array_agg(commodity_spec_id) AS commodities " +
                "       FROM system.product_spec_entry " +
                "       GROUP BY product_spec_id) ps " +
                "WHERE CAST(ARRAY[:commoditySpecIds] AS BIGINT[]) <@ CAST(ps.commodities AS BIGINT[])";
List<Long> commoditySpecsIds = commoditySpecs.stream().map(Spec::getId).collect(Collectors.toList());

List<BigInteger> productSpecIds = em.createNativeQuery(query).setParameter("commoditySpecIds", commoditySpecsIds)
                .getResultList();

它不起作用,因为我得到的记录数组()而不是bigint(ARRAY[(1692, 1868)]ARRAY[1692, 1868])

我应该如何将数组参数绑定到我的查询?也许我可以使用更简单的查询来查询它。


答案 1

从 SQL 中省略 :array[...]

WHERE CAST(:commoditySpecIds AS BIGINT[])

,然后将 ID 列表作为字符串传递,如下所示:

"{1,2,3,4}"

Lists 的默认 toString() 通常返回类似下面的内容:,因此您可以执行如下操作:"[1,2,3]"

String literal = commoditySpecsIds.toString();
literal = "{" + literal.substring(1,literal.length() - 1) + "};

然后将其传递到混淆层:

setParameter("commoditySpecIds", literal)

答案 2

我的情况完全相同。希望@VladMihalcea能帮助我们

编辑

我想用JPA来做这件事。在阅读了setParameter的入侵之后,我发现了类似于UserType的东西,TypedParameterValue。

当您使用时

setParameter("commoditySpecIds", new TypedParameterValue(IntArrayType.INSTANCE, commoditySpecsIds))

其中IntArrayType.INSTANCE来自Vlad Mihalcea提供的“hibernate-types”librairy。请注意,“commoditySpecsIds”必须是一个数组,而不是一个集合。

希望有所帮助


推荐