You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

能否通过JOOQ为主键生成值对象包装类?附示例说明

关于JOOQ生成主键值对象包装类的实现方案

完全可以通过JOOQ实现这种主键值对象的生成需求,主要有两种常用方式:


方式一:自定义代码生成器策略

JOOQ的代码生成器允许通过自定义策略修改实体类结构,你可以实现GeneratorStrategy接口或继承DefaultGeneratorStrategy,定制主键字段的类型并生成对应的包装类。

关键步骤:

  1. 创建自定义策略类:重写getJavaType()方法,将主键字段类型替换为目标值对象(如ProductIdentifier);同时添加逻辑自动生成值对象类。
  2. 配置代码生成器:在JOOQ生成配置中指定该自定义策略。

示例代码片段:

自定义策略类核心逻辑:

public class CustomGeneratorStrategy extends DefaultGeneratorStrategy {
    @Override
    public String getJavaType(Definition definition, Mode mode) {
        // 匹配product表的id主键字段
        if ("product".equals(definition.getTable().getName()) && "id".equals(definition.getName())) {
            return "com.yourpackage.ProductIdentifier";
        }
        return super.getJavaType(definition, mode);
    }

    // 自动生成ProductIdentifier类
    @Override
    public void generate(GeneratorContext context) {
        super.generate(context);
        if (context.getTable() != null && "product".equals(context.getTable().getName())) {
            generateProductIdentifierClass(context);
        }
    }

    private void generateProductIdentifierClass(GeneratorContext context) {
        JavaWriter writer = context.writer("com.yourpackage.ProductIdentifier");
        writer.println("public class ProductIdentifier {");
        writer.indent();
        writer.println("private final java.util.UUID id;");
        writer.println();
        writer.println("public ProductIdentifier(java.util.UUID id) {");
        writer.indent();
        writer.println("this.id = id;");
        writer.outdent();
        writer.println("}");
        writer.println();
        writer.println("public java.util.UUID getId() {");
        writer.indent();
        writer.println("return id;");
        writer.outdent();
        writer.println("}");
        // 补充equals、hashCode方法
        writer.println();
        writer.println("@Override");
        writer.println("public boolean equals(Object o) {");
        writer.indent();
        writer.println("if (this == o) return true;");
        writer.println("if (o == null || getClass() != o.getClass()) return false;");
        writer.println("ProductIdentifier that = (ProductIdentifier) o;");
        writer.println("return java.util.Objects.equals(id, that.id);");
        writer.outdent();
        writer.println("}");
        writer.println();
        writer.println("@Override");
        writer.println("public int hashCode() {");
        writer.indent();
        writer.println("return java.util.Objects.hash(id);");
        writer.outdent();
        writer.println("}");
        writer.outdent();
        writer.println("}");
        writer.close();
    }
}

XML配置中指定策略:

<configuration>
    <generator>
        <strategy>
            <name>com.yourpackage.CustomGeneratorStrategy</name>
        </strategy>
    </generator>
</configuration>

方式二:使用TypeConverter结合自定义类型

如果已有值对象,可通过JOOQ的TypeConverter实现类型转换,让生成的实体类直接使用值对象作为主键类型。

关键步骤:

  1. 手动定义值对象:
public class ProductIdentifier {
    private final UUID id;

    public ProductIdentifier(UUID id) {
        this.id = id;
    }

    public UUID getId() {
        return id;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        ProductIdentifier that = (ProductIdentifier) o;
        return java.util.Objects.equals(id, that.id);
    }

    @Override
    public int hashCode() {
        return java.util.Objects.hash(id);
    }
}
  1. 创建TypeConverter:
public class ProductIdentifierConverter implements TypeConverter<UUID, ProductIdentifier> {
    @Override
    public ProductIdentifier from(UUID databaseObject) {
        return databaseObject == null ? null : new ProductIdentifier(databaseObject);
    }

    @Override
    public UUID to(ProductIdentifier userObject) {
        return userObject == null ? null : userObject.getId();
    }

    @Override
    public Class<UUID> fromType() {
        return UUID.class;
    }

    @Override
    public Class<ProductIdentifier> toType() {
        return ProductIdentifier.class;
    }
}
  1. 配置代码生成器:
<configuration>
    <generator>
        <database>
            <forcedTypes>
                <forcedType>
                    <userType>com.yourpackage.ProductIdentifier</userType>
                    <converter>com.yourpackage.ProductIdentifierConverter</converter>
                    <includeTables>product</includeTables>
                    <includeColumns>id</includeColumns>
                </forcedType>
            </forcedTypes>
        </database>
    </generator>
</configuration>

生成的Product类中,id字段类型会自动变为ProductIdentifier。


两种方式各有优劣:第一种可自动生成值对象类,无需手动编写;第二种更灵活,适合已有值对象的场景,可根据实际需求选择。

内容的提问来源于stack exchange,提问作者Alex Korotkov

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 07:15:32