【问题标题】:JOOQ SUM in Kotlin with custom types带有自定义类型的 Kotlin 中的 JOOQ SUM
【发布时间】:2020-08-29 12:07:12
【问题描述】:

目前我有一个转换器可以使用 Kotlin 处理 JOOQ 中的值对象。

我的数据库有一个名为 transactions 的表,其字段类型为 decimal(10, 2),名为 billing _amount,在我的 Kotlin 代码中,我有一个来自 DDD 的简单 ValueObject 来包装它,名为 BillingAmount,定义如下

data class BillingAmount(val value: BigDecimal)

至于我的 jooq 自定义转换器,我有以下代码:

public final TableField<TransactionsRecord, BillingAmount> BILLING_AMOUNT =
        createField(
                DSL.name("billing_amount"),
                org.jooq.impl.SQLDataType.NUMERIC(10, 2).nullable(false),
                this,
                "",
                org.jooq.Converter.ofNullable(
                    java.math.BigDecimal.class,
                    okano.dev.jooqtesting.BillingAmount.class,
                    t -> new okano.dev.jooqtesting.BillingAmount(t),
                    u -> u.getValue()
                )
        );

在我的存储库中,我只是想检索一个帐单金额的总和,但 jooq 抱怨 BillingAmount 没有扩展 Number 类。我知道这是一个阻止我的代码工作的 Java 通用验证,但是除了扩展 Number 类之外,还有什么办法可以解决这个问题?我认为转换器应该足够了,但我肯定错了。

这是我想要实现的简单查询:

// jooq is an instance of DSLContext
return jooq.select(sum(TABLE.BILLING_AMOUNT))
            .from(TABLE)
            .fetchSingle()

对这个问题有什么想法吗?提前致谢。

【问题讨论】:

  • 试试TABLE.BILLING_AMOUNT.coerce(BigDecimal.class)
  • @M.Prokhorov:事实上,这可能是一个答案。

标签: java sql kotlin aggregation jooq


【解决方案1】:

我认为您遇到的问题只是由于 Java 的类型系统造成的。

如果是这样,您可以简单地将字段coerce 更改为不同类型的查询,就像这样(诚然,混淆了查询定义代码):

BillingAmount sum = jooq
  .select(sum(TABLE.BILLING_AMOUNT.coerce(BigDecimal.class)))
  .from(TABLE)
  .fetchSingle(TABLE.BILLING_AMOUNT);

不过,它与原始查询中的结果类型不完全相同,因为它直接实现BillingAmount,而不是Record&lt;BillingAmount&gt;(因为强制后查询返回类型将是Record&lt;BigDecimal&gt;

【讨论】:

  • 结果对我来说现在不是很重要,因为我会做一些其他的验证,所以包装在这个值对象中可能对这个方法没有意义。使用强制它会强制调用我的转换器?我尝试了一种使用 cast 的不同方法,似乎有效,但不确定哪种方法最好。我会试试你的解决方案。
  • @WilliamOkano, 不,coerce 或多或少只是为了更改编译器感知的Field&lt;T&gt; 中的T,我认为,所以查询将返回BigDecimal,如果你只需致电fetchSingle()。应该调用转换器(我认为),因为您向 fetchSingle(field) 提供了一个字段。
【解决方案2】:

作为一种解决方法,您始终可以在 jOOQ 中使用 plain SQL templating

fun alternativeSum(field: Field<*>) = DSL.field("{0}", field.getDataType(), field)

【讨论】:

  • 感谢您告诉我,我会看看这个。
  • Lukas Eder 和 jooq 一起玩,才发现你是官方贡献者哈哈哈。总是很高兴看到维护人员愿意为像我这样的新手提供一些建议:) 谢谢,jooq 做得很好
  • @WilliamOkano:“官方贡献者”——我喜欢 :)
猜你喜欢
  • 2014-04-07
  • 2015-06-05
  • 2013-05-15
  • 2017-06-29
  • 2021-09-08
  • 2017-10-20
  • 1970-01-01
  • 2015-09-04
  • 1970-01-01
相关资源
最近更新 更多