如何使用 Jooq 映射实体?

How can I map entity using a Jooq?

我有一个问题:不知道如何映射 Jooq 查询的结果。

我有 2 个实体:付款方式和货币。 Payment method里面包含一个List。两者都存储在不同的表中。

我得到一个:

public Optional<PaymentMethod> getMethod(Long id) {
return this.dslContext.selectFrom(PAYMENT_METHOD)
    .where(
        PAYMENT_METHOD.ID.eq(id),
        PAYMENT_METHOD.DELETED.eq(false)
    ).fetchOptional().map(v -> methodDao.mapper().map(v));

也想获得货币,方法是:

return this.dslContext.select(asterisk())
    .from(PAYMENT_METHOD)
    .join(PAYMENT_METHOD_CURRENCY)
    .on(PAYMENT_METHOD_CURRENCY.METHOD_ID.eq(id))
    .where(
        PAYMENT_METHOD.ID.eq(id),
        PAYMENT_METHOD.DELETED.eq(false)
    )
    .fetch()
    .map(...)...

那么,我该如何进一步映射呢?

我决定在其他实体中使用单个实体,例如:

private PaymentProviderMethod mapMethod(Record record) {
final PaymentMethodRecord methodRecord = record.into(PAYMENT_METHOD);
final PaymentProviderRecord providerRecord = record.into(PAYMENT_PROVIDER);
return new PaymentProviderMethod(
    methodDao.mapper().map(methodRecord),
    providerDao.mapper().map(providerRecord));

但不知道在这种情况下如何映射列表。你能帮忙吗?

如果你想用 jOOQ 嵌套集合,那么你可能正在寻找 MULTISET or MULTISET_AGG operator along with ad-hoc conversion, which allows for type safe nesting collections directly in SQL, if your database product support SQL/XML or SQL/JSON

以下可能不是您要查找的确切查询,但您明白了:

// Assuming the usual static import:
import static org.jooq.impl.DSL.*;

ctx.select(
       PAYMENT_METHOD.ID,
       PAYMENT_METHOD.PROVIDER_ID,
       PAYMENT_METHOD.NAME,
       ...
       multiset(
           select(
               PAYMENT_METHOD_CURRENCY.ID,
               PAYMENT_METHOD_CURRENCY.NAME,
               ...
           )
           .from(PAYMENT_METHOD_CURRENCY)
           .where(PAYMENT_METHOD_CURRENCY.METHOD_ID.eq(PAYMENT_METHOD.ID))
       ).convertFrom(r -> r.map(Records.mapping(Currency::new)))
   )
   .from(PAYMENT_METHOD)
   .fetch(Records.mapping(PaymentMethod::new))

上面的例子使用 MULTISET 作为嵌套的相关子查询,但是你可以用 MULTISET_AGGJOINGROUP BY 子句做同样的事情,特别是如果您的方言不支持 correlating derived tables, see issue #12045。整个查询是类型安全的。如果您更改 PaymentMethodCurrency DTO 类,查询将停止编译,直到您修复预测。

如果你使用的 Jooq 版本低于 13.15 那么你不能使用 multiset。对我来说,我遇到了同样的问题,我通过手动映射记录解决了这个问题。我用 Kotlin 做到了这一点,但我认为你可以从那里弄清楚这个想法:

private fun mapRecords(records: Result<Record>): List<PaymentMethod> {
        val paymentMethodCurrencies = records.into(PaymentMethodCurrencyRecord::class.java)
            .map(::mapPaymentMethodCurrency)
            .groupBy { it.paymentMethodId }

        val paymentMethods = records.into(PaymentMethodRecord::class.java).distinct()
            .map { 
                mapPaymentMethod(it, paymentMethodCurrencies[it.id])
            }

        return paymentMethods
    }