【问题标题】:PostgreSQL function used in QueryDSL is not working, returns ERROR: syntax error at or near "."QueryDSL 中使用的 PostgreSQL 函数不起作用,返回 ERROR: syntax error at or near "."
【发布时间】:2022-01-20 09:07:36
【问题描述】:

这是我关于stackoverflow的第一个问题,如果有任何不准确的地方,请提前道歉

在我的项目中,我使用 Hibernate(作为 ORM 框架)和 QueryDSL 库,PostgreSQL 作为数据库。

基本上,我需要检查列表“arr”的大小,这是某个“X”类的属性,所以我用谷歌搜索并找到了一种使用带有 querydsl 的 postgres 函数的方法,如下所示(在你问之前,我按要求不能使用本机查询):

BooleanBuilder builder = new BooleanBuilder();

builder.and(Expressions.booleanTemplate("function('array_length', {0})", qX.arr)
                .castToNum(Integer.class).gt(0));

一切编译正常,但是当调用存储库方法时,我得到一个错误:

错误:“.”处或附近的语法错误职位:...

我检查了所有内容,但没有“。”在那个位置和附近的位置也是如此。 但是设置spring.jpa.show-sql=true后发现确实有一个“.”符号在该位置的某处,结果 SQL 语句如下所示:

... and cast(array_length(.) as int4)>?

这意味着,JPA 不能将我的 'arr' 放入 array_length() 函数中(是这样吗?)

为什么会这样?难道我做错了什么? 提前谢谢你

我的实体类是这样的:

    @EqualsAndHashCode(callSuper = true)
    @Entity
    @Table
    @Data
    @NoArgsConstructor
    @TypeDefs({
            @TypeDef(name = "list-array", typeClass = ListArrayType.class)
    })
    public class X extends BaseClass {
    
        // private fields
    
        @Type(type = "list-array")
        @Column(name = "arr", columnDefinition = "bigint[]")
        @ElementCollection
        @OrderColumn
        private List<Long> arr;
    }

我尝试不使用 @ElementCollection 和 @OrderColumn 注释,但这给了我投射错误

【问题讨论】:

  • 你能添加你的实体类来展示数组类型是如何指定的吗?
  • @fladdimir 是的,当然。我已经更新了我的问题
  • 这里好像有2个问题,希望答案有帮助?
  • 不确定您使用的是哪个 ListArrayType 实现,但我已经为 Hibernate-Types 实现了 Querydsl 绑定,它也有 array_length 支持:github.com/jwgmeligmeyling/hibernate-types-querydsl-apt
  • @Jan-WillemGmeligMeyling 我用的是com.vladmihalcea.hibernate.type.array.ListArrayType,不过我会看看你的建议,谢谢!

标签: postgresql hibernate jpa jpql querydsl


【解决方案1】:

@ElementCollection@OrderColumn 在这里引起了第一个问题。删除它们(并且正确设置架构)后,需要更正函数调用(SQL 模板)。


@ElementCollection@OrderColumn 的问题在于,它们代表了将列表/数组作为实体的一部分存储的替代方法。
@ElementCollection 将元素存储在单独的表中,每个元素都在一个单独的行(每个引用实体)。为了“记住”正确的顺序,@OrderColumn 需要作为单独表的一部分,因为如果未指定顺序,行将按任意顺序返回 (https://stackoverflow.com/a/20050403)。

相比之下,ListArrayType@Column(columnDefinition = "bigint[]") 将允许将元素序列保存在实体行的一列中。因此,没有使用单独的表格,并且由于元素没有保存在单独的行中,因此不需要额外的订单信息。

所以没有@ElementCollection@OrderColumn 列表映射已经正确设置。请注意,您的架构当前可能处于错误状态,并且您需要确保实体表中有 bigint[] 列(例如,当 @ElementCollection@OrderColumn 被删除时,可以由休眠自动创建)。


2. 修复 PostgresQL 函数调用:array_length 需要第二个参数来指示返回长度的数组的维度 (https://www.postgresql.org/docs/current/functions-array.html)。因此,如下指定模板字符串应该会得到正确的结果:
"function('array_length', {0}, 1)"
(“1”是请求的数组维度)。

【讨论】:

  • 谢谢你,@fladdimir!这确实是我对模板的错误使用——我在我的 Postgres 方言中将 array_length 函数注册为 registerFunction("array_length", new StandardSQLFunction("array_length", StandardBasicTypes.INTEGER)); 认为它会自动将“1”作为数组维度放置,但是哦,好吧。在我手动设置尺寸后,一切都开始工作了!它没有检索任何数据,但这是另一个问题:)
  • 至于那些注释,事实证明,我并不真正需要它们。在我删除它们之后,没有发生任何不好的事情。我的专栏已经有了必要的类型,并且架构处于正确的状态
猜你喜欢
  • 1970-01-01
  • 2022-11-11
  • 1970-01-01
  • 1970-01-01
  • 2015-04-24
  • 2020-05-25
  • 1970-01-01
  • 2014-05-02
  • 1970-01-01
相关资源
最近更新 更多