有时,当函数具有如下特征时,它可能会变得毛茸茸:
fun doStuff(firstKey: UUID, secondKey: UUID, ...)
对于编译器而言,所有UUID都是相同的,因此希望在运行时数据库能够在此捕获问题。
我喜欢jOOQ在编译时如何解决许多问题,我也想解决这个问题。我的目标是为每个表的每个键都有自己的类,并使用这些字段正确生成pojo。
实现这一目标的最佳方法是什么?我提出了以下建议:
JavaGenerator
的实现Converters
,其中包含许多强制类型映射和手动创建的键类有人有类似的经验吗?
答案 0 :(得分:1)
您不是第一个有这个想法的人。有一个未决的功能请求,可以立即生成此类“密钥包装器”类(在3.11中尚不可用): https://github.com/jOOQ/jOOQ/issues/6124
或者这个讨论: https://groups.google.com/forum/#!topic/jooq-user/53RZqoewa3g
此功能还有其他应用程序。一旦此类类型存在:
复合键案例使jOOQ难以立即使用,因为首先需要实现各种附加功能才能将几列分组为一个合成列。另外,唯一键和外键都可以重叠,因此必须考虑很多边缘情况。
您可以自己实现。如果您的架构仅具有单列代理键,则可以覆盖JavaGenerator
类并为每个表生成一个附加类,然后以编程方式将相关的forcedType
配置和Converter
实现添加到代码生成器中配置。
其他人可能已经做了类似的事情,但是我不知道任何公开可用的实现。
原则上,您也可以直接在数据库中实现此功能,例如如果您使用的是PostgreSQL。您可以将UUID包装为复合类型,并将其用于主键/外键:
create type pk_a as (id bigint);
create type pk_b as (id bigint);
create table t_a(id pk_a primary key);
create table t_b(id pk_b primary key, a pk_a references t_a);
insert into t_a values(row(1)::pk_a);
insert into t_b values(row(2)::pk_b, row(1)::pk_a);
jOOQ代码生成器应该选择这些类型并为您做正确的事情。当然,考虑到我很少在野外看到这种做法,可能有很多警告:-)
答案 1 :(得分:1)
有人有类似的经验吗?
是的,我已经在Java和Kotlin项目中做到了。所有表都使用基于UUID的代理键,并遵循以下命名约定:
ADDRESS.ID
ORDER.ADDRESS_ID
或ORDER.SHIPPING_ADDRESS_ID
对于Kotlin项目,我使用了
这大约需要2天的时间才能正确设置,并极大地提高了类型安全性和代码清晰度。恕我直言,为一个估计超过1个人年的项目付出的努力是值得的。
(实际上,我进一步走了一步,编写了一个小的“代码脚手架”工具,该工具会生成上述三个工件。这使我不必在不同位置摆弄文件,这虽然容易出错,但通常很烦人。这我花了一天的时间写,尽管这在很大程度上取决于您的项目设置。)
我们之所以选择不通过自定义JooqGenerator
实现来解决此问题,是因为我们也在域代码中使用了相同的XXXId类,出于架构上的原因,这些类不能依赖于数据层构件。我们对枚举使用近似相同的方法,事实证明,在JOOQ模型中使用域类型(而不是相反)特别有用。例如,在代码中记录手动定义的枚举值很简单,这在生成的类中会丢失。我们还可以轻松定义ContactId
和CustomerId
之间的子类型关系,这对于生成的类来说非常麻烦。
我可以提供一些细节,以使您有一个更好的主意,但不幸的是,不是全部实现,因为那是我不拥有的专有代码。