类型安全映射一对一和一对多关系到记录
Type safe mapping one-to-one and one-to-many relationships to records
我想将一对一和一对多关系映射到生成的记录,最好以类型安全的方式。
我现在可以使用 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.
如果你想要类型安全,你不应该使用你使用过的两个功能:
- 手动 SQL/JSON API 用法,生成缺乏类型安全性的通用 JSON 文档
- 通过
into(X.class)
调用的反射映射,它利用了 DefaultRecordMapper
的反射映射功能。
上面的做法没有错。 jOOQ 3.14 引入了 SQL/JSON 支持以及 mapping JSON documents to Java objects using Gson or Jackson 的功能,如果在类路径中找到的话。该方法只是类型不安全。
现在,让我们分别看一下您的各个问题,您似乎在混淆问题...
One-to-one映射
从 jOOQ 3.17(尚未发布,但很快)开始,the Table<R>
type extends SelectField<R>
for convenience,这意味着您可以将任何 table 表达式投影为嵌套记录,并将其映射到您自己的自定义记录(或不):
// 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();
虽然没有必要,但上面的示例使用了 implicit joins,这大大简化了这样的查询。当然,您可以像以前一样继续使用显式连接。
在 jOOQ 3.16 中,您可以通过 nested row()
expression 的显式投影来做到这一点,就像这样。将嵌套记录映射到类型化的、生成的 UpdatableRecord
时没有类型安全,但我认为这是 acceptable,因为你仍在使用生成的代码,因此实际上不能有任何映射错误:
// 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();
One-to-many映射
当您使用 multisetAgg(rel.ID)
方法时,您的代码似乎出了问题,但我无法从您的问题中看出问题所在。另外,.
你的两个问题之间的唯一区别是,在这里,你不想使用 Java 记录,而是使用 jOOQ 生成的记录,在这种情况下你将使用这个习惯用法:
Field<Result<RelationRecord>> f = multisetAgg(rel.ID).convertFrom(r -> r.map(RELATION));
我想将一对一和一对多关系映射到生成的记录,最好以类型安全的方式。
我现在可以使用 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.
如果你想要类型安全,你不应该使用你使用过的两个功能:
- 手动 SQL/JSON API 用法,生成缺乏类型安全性的通用 JSON 文档
- 通过
into(X.class)
调用的反射映射,它利用了DefaultRecordMapper
的反射映射功能。
上面的做法没有错。 jOOQ 3.14 引入了 SQL/JSON 支持以及 mapping JSON documents to Java objects using Gson or Jackson 的功能,如果在类路径中找到的话。该方法只是类型不安全。
现在,让我们分别看一下您的各个问题,您似乎在混淆问题...
One-to-one映射
从 jOOQ 3.17(尚未发布,但很快)开始,the Table<R>
type extends SelectField<R>
for convenience,这意味着您可以将任何 table 表达式投影为嵌套记录,并将其映射到您自己的自定义记录(或不):
// 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();
虽然没有必要,但上面的示例使用了 implicit joins,这大大简化了这样的查询。当然,您可以像以前一样继续使用显式连接。
在 jOOQ 3.16 中,您可以通过 nested row()
expression 的显式投影来做到这一点,就像这样。将嵌套记录映射到类型化的、生成的 UpdatableRecord
时没有类型安全,但我认为这是 acceptable,因为你仍在使用生成的代码,因此实际上不能有任何映射错误:
// 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();
One-to-many映射
当您使用 multisetAgg(rel.ID)
方法时,您的代码似乎出了问题,但我无法从您的问题中看出问题所在。另外,
你的两个问题之间的唯一区别是,在这里,你不想使用 Java 记录,而是使用 jOOQ 生成的记录,在这种情况下你将使用这个习惯用法:
Field<Result<RelationRecord>> f = multisetAgg(rel.ID).convertFrom(r -> r.map(RELATION));