JOOQ - 如何将 array_agg 与自定义类型字段一起使用

Posted

技术标签:

【中文标题】JOOQ - 如何将 array_agg 与自定义类型字段一起使用【英文标题】:JOOQ - How to use array_agg with custom type field 【发布时间】:2019-10-09 19:43:20 【问题描述】:

我正在使用 Jooq(使用 PostgreSQL)。我需要在某些查询中使用array_agg,以从自定义类型的字段中聚合值。

 SELECT TABLE.FIELD1, array_agg(TABLE.FIELD2) FROM TABLE GROUP BY TABLE.FIELD1;

dslContext.select(TABLE.FIELD1, arrayAgg(TABLE.FIELD2))
            .from(TABLE)
            .groupBy(TABLE.FIELD1)
            .fetch();

FIELD2 是 DB 中的 int8 列,通常映射到 Java Long。

我已经定义了一个TypeConverterforcing 到某个 Java 类的转换。

转换在所有查询中都能正常工作,但在使用 array_agg 时会失败并出现异常:

Caused by: java.sql.SQLException: Error while reading field: array_agg("PUBLIC"."TABLE"."FIELD2"), at JDBC index: 2
        at org.jooq.impl.CursorImpl$CursorIterator$CursorRecordInitialiser.setValue(CursorImpl.java:1781)
        at org.jooq.impl.CursorImpl$CursorIterator$CursorRecordInitialiser.operate(CursorImpl.java:1740)
        at org.jooq.impl.CursorImpl$CursorIterator$CursorRecordInitialiser.operate(CursorImpl.java:1705)
        at org.jooq.impl.RecordDelegate.operate(RecordDelegate.java:125)
        at org.jooq.impl.CursorImpl$CursorIterator.fetchNext(CursorImpl.java:1669)
        ... 120 more
Caused by: org.jooq.exception.DataTypeException: Cannot convert from 15 (class java.lang.Long) to class <my custom class>
        at org.jooq.tools.Convert$ConvertAll.fail(Convert.java:1167)
        at org.jooq.tools.Convert$ConvertAll.from(Convert.java:1056)
        at org.jooq.tools.Convert.convert0(Convert.java:322)
        at org.jooq.tools.Convert.convert(Convert.java:314)
        at org.jooq.tools.Convert.convert(Convert.java:386)
        at org.jooq.tools.Convert.convertArray(Convert.java:293)
        at org.jooq.tools.Convert$ConvertAll.from(Convert.java:537)
        at org.jooq.tools.Convert.convert0(Convert.java:322)
        at org.jooq.tools.Convert.convert(Convert.java:314)
        at org.jooq.tools.Convert.convert(Convert.java:386)
        at org.jooq.impl.DefaultBinding$DefaultArrayBinding.convertArray(DefaultBinding.java:1128)
        at org.jooq.impl.DefaultBinding$DefaultArrayBinding.pgGetArray(DefaultBinding.java:1117)
        at org.jooq.impl.DefaultBinding$DefaultArrayBinding.get0(DefaultBinding.java:1033)
        at org.jooq.impl.DefaultBinding$DefaultArrayBinding.get0(DefaultBinding.java:912)
        at org.jooq.impl.DefaultBinding$AbstractBinding.get(DefaultBinding.java:775)
        at org.jooq.impl.CursorImpl$CursorIterator$CursorRecordInitialiser.setValue(CursorImpl.java:1771)

有什么解决方法吗?这是 JOOQ 的限制吗?

谢谢! 丹

【问题讨论】:

这可能与github.com/jOOQ/jOOQ/issues/7471有关吗? jOOQ 的作者 Lukas Eder 在那里提到该功能应该可以正常工作。也许尝试创建一个完整的、最小的复制示例并在该票中进行提示。另外,您使用的是哪个版本的 jOOQ? 感谢@PetrJaneček 提供问题参考,看来我遇到了同样的问题。我用最新的 JOOQ 版本 (3.11.11) 进行了尝试,并且该问题可以在该版本上重现。 【参考方案1】:

我最终得到了以下解决方法:

dslContext.select(TABLE.FIELD1, arrayAgg(TABLE.FIELD2).coerce(Long[].class))
            .from(TABLE)
            .groupBy(TABLE.FIELD1)
            .fetch();

在获取后将 Long 转换为我的自定义类型。

【讨论】:

以上是关于JOOQ - 如何将 array_agg 与自定义类型字段一起使用的主要内容,如果未能解决你的问题,请参考以下文章

如何将两组与自定义数据类型进行比较

如何将 QSGClipNode 与自定义几何图形一起使用?

如何将 Qt 属性与自定义类一起使用?

如何将 DataAnnotations ErrorMessageResourceName 与自定义资源解决方案一起使用

OpenCV:如何将 HOGDescriptor::detectMultiScale() 与自定义 SVM 一起使用?

如何将 boost::unordered_set 与自定义类一起使用?