键入到记录的一对一和一对多关系的安全映射



我想将一对一和一对多的关系映射到生成的记录,最好是以类型安全的方式。

我现在可以使用Java记录,但我更愿意使用代码生成的records,这样之后我可以更容易地更新它们,尽管我不需要Record的所有列。

我还有一个问题,不是没有将联系人映射到列表,而是映射到列表中,而它确实正确地映射了地址。

record BulkContactEdit(long id, String organizationName, List < Contact > contacts, Address visitedAddress) {}
record Contact(long id) {}
record Address(long id, String address, String state, String city, String zipcode, Long country_id) {}
var bce = BULK_CONTACT_EDIT.as("bce");
var bceContacts = BULK_CONTACT_EDIT_CONTACTS.as("bceContacts");
var rel = RELATION.as("rel");
var bceAddress = ADDRESS.as("bceAddress");
var query = jooq().select(
bce.ID, bce.ORGANIZATION_NAME,
// For some reason this doesn't map.
//                DSL.multisetAgg(rel.ID)
//                    .as("contacts")
//                    .convertFrom(r -> r.map(mapping(Contact::new))),
jsonArrayAgg(jsonObject(rel.ID)).as("contacts"), jsonObject(bceAddress.fields()).as("visitedAddress"))
// Same as above, but with redundant sub-query.
//                DSL.field(
//                        jooq()
//                            .select(jsonArrayAgg(jsonObject(rel.ID)))
//                            .from(rel)
//                            .where(rel.ID.eq(bceContacts.CONTACT_ID)))
//                    .as("contacts"))
.from(
bce.join(bceContacts).on(bceContacts.BULK_CONTACT_EDIT_ID.eq(bce.ID)).join(rel).on(rel.ID.eq(bceContacts.CONTACT_ID)).leftJoin(bceAddress).on(bceAddress.ID.eq(bce.VISIT_ADDRESS_ID)).where(bce.ID.eq(bulkContactEditId)));
var bulkContactEdit = query.fetchOneInto(BulkContactEdit.class);

关于类型安全

我想将一对一和一对多的关系映射到生成的记录,最好是以类型安全的方式。

如果你想要类型安全,你不应该使用你使用过的两个功能:

  • 手动使用SQL/JSON API,生成缺乏类型安全性的通用JSON文档
  • 通过into(X.class)调用进行反射映射,该调用利用了DefaultRecordMapper的反射映射功能

上述方法没有错。jOOQ 3.14引入了SQL/JSON支持,以及使用Gson或Jackson将JSON文档映射到Java对象的功能(如果在类路径中找到的话(。这种方法就是不安全。

现在,让我们单独来看一下你的个人问题,你似乎在混合担忧。。。

一对一映射

从jOOQ 3.17(尚未发布,但很快就会发布(开始,为了方便起见,Table<R>类型扩展了SelectField<R>,这意味着您可以将任何表表达式投影为嵌套记录,并将其映射到您自己的自定义记录(或不映射(:

// Using implicit joins, mixing scalar values and nested records
Result<Record3<Long, String, AddressRecord>> r1 =
ctx.select(bce.ID, bce.ORGANIZATION_NAME, bce.address())
.from(bce)
.fetch();
// Using implicit joins, projecting only nested records
Result<Record2<BulkContactEditRecord, AddressRecord>> r1 =
ctx.select(bce, bce.address())
.from(bce)
.fetch();

虽然没有必要,但上面的示例使用了隐式联接,这大大简化了这样的查询。当然,您可以像以前一样继续使用显式联接。

在jOOQ 3.16中,您可以通过嵌套row()表达式的显式投影来实现这一点,如下所示。将嵌套记录映射到类型化、生成的UpdatableRecord时没有类型安全性,但我认为这是可以接受的,因为您仍在使用生成的代码,因此不会出现任何映射错误:

// Using implicit joins, mixing scalar values and nested records
Result<Record3<Long, String, AddressRecord>> r1 =
ctx.select(
bce.ID, 
bce.ORGANIZATION_NAME, 
row(bce.address().fields()).convertFrom(r -> r.into(ADDRESS)))
.from(bce)
.fetch();
// Using implicit joins, projecting only nested records
Result<Record2<BulkContactEditRecord, AddressRecord>> r1 =
ctx.select(
row(bce.fields()).convertFrom(r -> r.into(BULK_CONTACT_EDIT)), 
row(bce.address().fields()).convertFrom(r -> r.into(ADDRESS)))
.from(bce)
.fetch();

一对多映射

当您使用multisetAgg(rel.ID)方法时,您的代码中似乎出现了问题,但我从您的问题中看不出问题出在哪里。此外,这与你之前的问题没有什么不同,之前的问题已经有了如何做到这一点的答案。

您的两个问题之间的唯一区别是,在这里,您不喜欢使用Java记录,而是使用jOOQ生成的记录,在这种情况下,您将使用以下习语:

Field<Result<RelationRecord>> f = multisetAgg(rel.ID).convertFrom(r -> r.map(RELATION));

最新更新