【问题标题】:Syntax for using postgresql array overlay operator in queryDSL在 queryDSL 中使用 postgresql 数组覆盖运算符的语法
【发布时间】:2021-01-16 15:23:39
【问题描述】:

我正在尝试构建一个查询,该查询在 queryDSL + JPA 中使用 postgresql 的数组覆盖运算符,使用 BooleanBuilder 和布尔模板,但是我无法让 JPA 接受我的查询。我目前写的方式是

    public BooleanBuilder addUUIDListIntersectionCondition(BooleanBuilder clause,
        CollectionPath<UUID, ComparablePath<UUID>> arg0, List<UUID> arg1) {
        clause.and(Expressions.booleanTemplate("{0} && ARRAY[{1}::UUID]", arg0,
            String.join(",", arg1.stream().map(a -> a.toString()).collect(Collectors.toList()))));
    }

但这会导致以下异常:

An exception occurred while creating a query in EntityManager: 
Exception Description: Syntax error parsing [select ec
from vw_ec ec
where ec.orgUserIds && ARRAY[?1::UUID]]. 
[76, 193] The expression is not a valid conditional expression.; nested exception is java.lang.IllegalArgumentException: An exception occurred while creating a query in EntityManager: 
Exception Description: Syntax error parsing [select ec
from vw_ec ec
where ec.orgUserIds && ARRAY[?1::UUID]]. 
[76, 193] The expression is not a valid conditional expression.
    at org.springframework.orm.jpa.EntityManagerFactoryUtils.convertJpaAccessExceptionIfPossible(EntityManagerFactoryUtils.java:374)
    at org.springframework.orm.jpa.DefaultJpaDialect.translateExceptionIfPossible(DefaultJpaDialect.java:128)
    at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.translateExceptionIfPossible(AbstractEntityManagerFactoryBean.java:528)
    at org.springframework.dao.support.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:61)
    at org.springframework.dao.support.DataAccessUtils.translateIfNecessary(DataAccessUtils.java:242)

直接在 postgresql 中运行类似的查询按预期工作:

select *
    from ec ec
    where (ec.orgUserIds && array['c61d452e-0361-11eb-8ecd-9e48108033fa', 'c623fc2d-0361-11eb-8ecd-9e48108033fa'::UUID])

关于我哪里出错了有什么想法吗?

【问题讨论】:

  • 我尝试将覆盖操作符包装在数据库函数中并调用它,但现在我得到内部异常:java.lang.ClassCastException: class org.eclipse.persistence.mappings.structures.ArrayMapping当我尝试调用该函数时,无法将其转换为类 org.eclipse.persistence.mappings.CollectionMapping。
  • 如果您已经弄清楚应该如何使用完全相同的查询 ec.orgUserIds && array['c61d452e-0361-11eb-8ecd-9e48108033fa', 'c623fc2d-0361- 11eb-8ecd-9e48108033fa']::uuid[]。我遇到了同样的问题。
  • 我已经设法使这样的查询可行 c.orgUserIds && array['c61d452e-0361-11eb-8ecd-9e48108033fa']::uuid[] 其中 arg1 只有一个使用 booleanTemplate 的元素: "Expressions.booleanTemplate("{0} && ARRAY[{1}]::uuid[]", ec.orgUserIds, StringUtils.collectionToDelimitedString(arg1, ",", "'", "'"))" 但是这个语法如果 arg1 有超过 1 个元素,则对我不起作用 - 抛出 PostgresqlBadGrammarException:不正确的 UUID 长度。 QueryDSL 模板看起来像是将 ARRAY 的整个输入参数解释为字符串。使用 string_to_array 而不是 ARRAY 对我也没有帮助

标签: postgresql jpa querydsl


【解决方案1】:

不要认为我有干净的解决方案,但它适用于以下查询:

select *
from ...
where '{e48f54d5-9845-4987-a53d-e0ecfe3dbb43,e48f54d5-9845-4987-a53d-e0ecfe3dbb45}'::uuid[] && '{e48f54d5-9845-4987-a53d-e0ecfe3dbb40,e48f54d5-9845-4987-a53d-e0ecfe3dbb45}'::uuid[];

我在booleanTemplate 中使用以下语法:

select(...)
.from(...)
.where(new BooleanBuilder().and(Expressions.booleanTemplate("{0} && {1}::uuid[]", arg0, String.format("{%s}", arg1.stream().map(UUID::toString).collect(joining(",")))))

【讨论】:

  • 哦,很有趣,所以您可以通过在 select 语句中而不是在 where 中使用 booleanTemplate 来使其工作?这比不能全部使用要好,但如果能够按功能过滤也很好。
  • 我一直在尝试您的建议,但在查询实际执行之前,我总是在 JPA 中遇到错误。 [1258, 1504] 表达式不是有效的条件表达式。 [1504, 1814] 查询包含格式错误的结尾。] 2020-10-16 22:09:57.230 调试 10 --- [nio-8080-exec-6] o.j.s.OpenEntityManagerInViewInterceptor:在 OpenEntityManagerInViewInterceptor 中关闭 JPA EntityManager
  • 我更正了答案,它会清楚一点。 BooleanTemplate 用于 where 子句。试试这个例子。
猜你喜欢
  • 2013-01-27
  • 2023-03-29
  • 2012-04-25
  • 1970-01-01
  • 2010-12-11
  • 2010-12-26
  • 1970-01-01
  • 1970-01-01
  • 2019-04-07
相关资源
最近更新 更多