Nesting MULTISET/ROW/MULTISET/ROW with ad-hoc converters and JSON emulation results in ClassCastException

huangapple go评论67阅读模式
英文:

Nesting MULTISET/ROW/MULTISET/ROW with ad-hoc converters and JSON emulation results in ClassCastException

问题

代码示例中描述了一个问题,涉及到多层嵌套的子查询,但结果的类型与预期不符。期望的结果类型是List<List<Tuple2>>,但实际上似乎是ArrayList<ArrayList<ArrayList>>,这似乎是行类型的原始表示。

问题的输出如下:

The result: [[[[Hello, World]]]]
The tuple: [[Hello, World]]
An unhandled error occurred
java.lang.ClassCastException: class java.util.ArrayList cannot be cast to class com.mycompany.mypackage.MyClass$1Tuple2 (java.util.ArrayList is in module java.base of loader 'bootstrap'; com.mycompany.mypackage.MyClass$1Tuple2 is in unnamed module of loader 'app')

这是一个与 jOOQ 版本 3.17.8 以及 MySQL 8.0.28 数据库一起使用的问题。使用的 Java 版本是 openjdk 19.0.1。JDBC 驱动程序是 mysql:mysql-connector-java:8.0.31。

英文:

When performing a select which includes a subquery in multiselect, which itself performs a subquery in a multiset, I would expect the result to have the expected type.

Instead, the nested result appears to be left as an ArrayList and not serialized properly to the target type.

Steps to reproduce the problem

record Tuple2(String t1, String t2) {}

var result = db.select(
    multiset(
        select(
            row(
                multiset(
                    select(
                        row(&quot;Hello&quot;, &quot;World&quot;).mapping(Tuple2::new)
                    ).from(dual())
                ).convertFrom(r -&gt; r.map(Record1::component1))
            ).mapping(r -&gt; r)
        ).from(dual())
    ).convertFrom(r -&gt; r.map(Record1::component1))
).from(dual())
.fetchOne(Record1::component1);

log.debug(&quot;The result: {}&quot;, result);
log.debug(&quot;The tuple: {}&quot;, result.get(0).get(0));
log.debug(&quot;The type of the result: {}&quot;, result.get(0).get(0).getClass());

The expected type of result is List&lt;List&lt;Tuple2&gt;&gt; but instead it appears to be ArrayList&lt;ArrayList&lt;ArrayList&gt;&gt; (I'm guessing the raw representation of the row type).

The output of this code is:

The result: [[[[Hello, World]]]]
The tuple: [[Hello, World]]
An unhandled error occurred
java.lang.ClassCastException: class java.util.ArrayList cannot be cast to class com.mycompany.mypackage.MyClass$1Tuple2 (java.util.ArrayList is in module java.base of loader &#39;bootstrap&#39;; com.mycompany.mypackage.MyClass$1Tuple2 is in unnamed module of loader &#39;app&#39;)

jOOQ Version

3.17.8

Database product and version

MySQL 8.0.28

Java Version

openjdk version "19.0.1" 2022-10-18

OS Version

No response

JDBC driver name and version (include name if unofficial driver)

mysql:mysql-connector-java:8.0.31

答案1

得分: 2

这是一个在 jOOQ 3.18.0、3.17.9 和 3.16.15 中修复的错误: https://github.com/jOOQ/jOOQ/issues/14657

这个错误只影响了 MULTISET 运算符的 JSON 模拟,而不影响 XML 模拟,尽管这对于不支持 SQL/XML 的 MySQL 来说并没有帮助。

正如在错误讨论中所指出的,这个特定问题可以通过省略其中一个 row() 运算符来解决:

var result = db.select(
    multiset(
        select(
            // row( 在这种情况下不需要
                multiset(
                    select(
                        row("Hello", "World").mapping(Tuple2::new)
                    ).from(dual())
                ).convertFrom(r -> r.map(Record1::component1))
            // ).mapping(r -> r)
        ).from(dual())
    ).convertFrom(r -> r.map(Record1::component1))
).from(dual())
.fetchOne(Record1::component1);

我明白这只是一个简化的复制示例,实际查询更加复杂,不过也许这可以帮助在实际查询中解决问题,直到修复可用为止。

英文:

This is a bug that was fixed in jOOQ 3.18.0, 3.17.9, and 3.16.15: https://github.com/jOOQ/jOOQ/issues/14657

The bug only affected JSON emulations of the MULTISET operator, not XML emulations, though that doesn't help as a workaround for MySQL, which doesn't support SQL/XML.

As noted in the bug discussion, this particular problem can be worked around by omitting one of the row() operators:

var result = db.select(
    multiset(
        select(
            // row( Unnecessary in this case
                multiset(
                    select(
                        row(&quot;Hello&quot;, &quot;World&quot;).mapping(Tuple2::new)
                    ).from(dual())
                ).convertFrom(r -&gt; r.map(Record1::component1))
            // ).mapping(r -&gt; r)
        ).from(dual())
    ).convertFrom(r -&gt; r.map(Record1::component1))
).from(dual())
.fetchOne(Record1::component1);

I realise that this is just a simplified reproducer, the real query being more complex, though perhaps this helps work around the problem also in the real query, until the fix is available.

huangapple
  • 本文由 发表于 2023年3月3日 18:11:44
  • 转载请务必保留本文链接:https://go.coder-hub.com/75625725.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定