JOOQ:Result.getValues()返回带有null条目的列表

时间:2014-07-25 01:36:34

标签: sql many-to-many jooq

我使用JOOQ查询多对多关系,并且需要将一个条目的多个结果映射到单个对象中。为此,我使用唯一标识符将结果提取到组中,并从每个分组结果中提取所需数据。对于多对多数据,我得到所有可用值,对于普通数据,我只使用第一个条目的数据:

Map<String, Result<Record2<String, String>> groupedResults = create.select(LOC.NAME, GROUP.GROUP_)
    .from(LOC)
    .leftOuterJoin(LOC2GROUP)
    .on(Tables.LOC2GROUP.LOC_ID.eq(LOC.LOC_ID))
    .leftOuterJoin(GROUP)
    .on(LOC2GROUP.GROUP_ID.eq(GROUP.GROUP_ID))
    .fetch().intoGroups(LOC.NAME);

Collection<Loc> ret = new ArrayList<Loc>();
for (Result<Record2<String, String>> result : groupedResults.values()) {
    Loc loc = new Loc(result.getValue(0, LOCATION.NAME), result.getValues(Tables.GROUP.GROUP_));
    ret.add(loc);
}

现在,虽然每个条目都可以有多个组,但它不需要任何组,以下将是一个有效的条目,只是没有任何组设置:

|name  |group |   
|simple|{null}|

奇怪的是,我注意到Result.getValues()在这种情况下返回包含null的List,而不是空列表。

这是否有意,如果有的话,是否有比在获取后删除空条目更好的解决方法?

1 个答案:

答案 0 :(得分:2)

您在查询中使用OUTER JOIN。这意味着您的结果集可能确实包含来自LOC表的值,但没有来自GROUP表的相应值。以下是查询的一些有效示例输出:

+------+--------+
| name | group  |
+------+--------+
| a    | x      |
| a    | y      |
| b    | x      |
| c    | {null} | <-- there's a value in LOC, but no corresponding value in GROUP
+------+--------+

现在,当您在该结果上调用jOOQ的intoGroups()时,jOOQ只会看到3个组:abc,它们会为您提供以下内容{{ 1}}(使用JSON作为伪表示法):

Map

仅仅因为其中一列中恰好有{ "a" : [ { "name" : "a", "group" : "x" }, { "name" : "a", "group" : "y" } ], "b" : [ { "name" : "b", "group" : "x" } ], "c" : [ { "name" : "c", "group" : null } ] } 值并不意味着此null值在分组时应具有任何语义。事实上,这一列(null)是您感兴趣的唯一列,并不会改变分组结果是记录而不是单个值的事实。

我希望这有道理吗?

jOOQ目前不支持返回您真正需要的数据结构的方法:

group

但是自己编写这样的实用方法应该相当容易......

PostgreSQL或HSQLDB解决方案:

或者,如果您使用的是PostgreSQL或HSQLDB,则可以使用array_agg()代替:

{
    "a" : [ "x", "y" ],
    "b" : [ "x" ],
    "c" : [ ]
}

Result<Record2<String, String[]>> result = create.select(LOC.NAME, arrayAgg(GROUP.GROUP_)) .from(LOC) .leftOuterJoin(LOC2GROUP) .on(Tables.LOC2GROUP.LOC_ID.eq(LOC.LOC_ID)) .leftOuterJoin(GROUP) .on(LOC2GROUP.GROUP_ID.eq(GROUP.GROUP_ID)) .groupBy(LOC.NAME) .fetch(); 将成为jOOQ 3.5的一部分,但你可以自己创建jOOQ功能:

DSL.arrayAgg()