将一对一和一对多关系映射到记录的类型安全
我想将一对一和一对多关系映射到生成的记录,最好以类型安全的方式。
我现在可以使用 Java 记录进行此操作,但我宁愿使用代码生成的记录,这样我以后就可以更轻松地更新它们,尽管我不需要记录的所有列。
我还遇到的问题不是不将联系人映射到列表,而是映射到列表,同时它确实正确映射了地址。
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);
I want to map one-to-one and one-to-many relationships to generated Records, preferably in a type-safe manner.
I now have this working with Java records, but I would rather use the code generated Records, so I can update them easier afterwards, though I don't need all the columns of a Record.
I also have the problem that isn't doens't map the contacts to a List but to a List while it does map the Address correctly.
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);
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
关于类型安全
如果您想要类型安全,则不应使用已使用过的 2 个功能:
into(X.class)
调用,使用DefaultRecordMapper
的反射映射功能。上面的做法没有什么问题。 jOOQ 3.14 引入了 SQL/JSON 支持以及 如果在类路径上找到,则使用 Gson 或 Jackson 将 JSON 文档映射到 Java 对象。该方法不是类型安全的。
现在,让我们单独看看您的个人问题,您似乎在混合关注点...
一对一映射
从 jOOQ 3.17 开始(尚未发布,但很快),
Table
类型扩展SelectField
为了方便,这意味着您可以将任何表表达式投影为嵌套记录,并将其映射到您自己的自定义记录(或不映射):虽然不是必需的,但上面的示例使用 隐式join,这大大简化了这样的查询。当然,您可以像以前一样继续使用显式联接。
在 jOOQ 3.16 中,您可以通过 嵌套
row()
表达式,像这样。将嵌套记录映射到类型化的生成的 UpdatableRecord 时不存在类型安全,但我认为这是可以接受的,因为您仍在使用生成的代码,因此实际上不会有任何映射错误:一对多映射
当您使用
multisetAgg(rel.ID)
方法时,您的代码中似乎出现了问题,但我看不出可能是什么问题你的问题。另外,这与您上一个问题并没有什么不同,上一个问题已经有关于如何执行此操作的答案。你的两个问题之间的唯一区别是,在这里,你不喜欢使用 Java 记录,而是使用 jOOQ 生成的记录,在这种情况下,你将使用以下习惯用法:
Regarding type safety
If you want type safety, you should not use 2 of the features you've used:
into(X.class)
calls, which make use of theDefaultRecordMapper
's reflective mapping capabilities.There's nothing wrong with the above approach. jOOQ 3.14 introduced SQL/JSON support as well as the capability of mapping JSON documents to Java objects using Gson or Jackson, if found on the classpath. The approach is just not type safe.
Now, let's look at your individual questions individually, you seem to be mixing concerns...
One-to-one mapping
Starting with jOOQ 3.17 (not yet released, but soon), the
Table<R>
type extendsSelectField<R>
for convenience, which means you can project any table expression as a nested record, and map it to your own custom record (or not):While not necessary, the above example makes use of implicit joins, which greatly simplify a query like this. Of course, you can continue using explicit joins like you did.
In jOOQ 3.16, you can do this via an explicit projection of a nested
row()
expression, like this. There is no type safety when mapping the nested record to a typed, generatedUpdatableRecord
, but I think that's acceptable, given that you're still using generated code and as such can't really have any mapping errors:One-to-many mapping
There seems to have been something going wrong in your code when you used the
multisetAgg(rel.ID)
approach, but I can't see what could have been the problem from your question. Also, it's not really a different question from your previous one, which already has an answer on how to do this.The only difference between your two questions is that here, you prefer not to use a Java record, but jOOQ's generated records, in case of which you'll use this idiom: