我使用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,而不是空列表。
这是否有意,如果有的话,是否有比在获取后删除空条目更好的解决方法?
答案 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个组:a
,b
和c
,它们会为您提供以下内容{{ 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,则可以使用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()