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

如何通过SQL查询配置jOOQ Embeddable Types代码生成映射规则

jOOQ自动映射同规则嵌入式类型的最优配置方案

核心思路:利用jOOQ代码生成器的可编程扩展接口,基于你的统一字段命名规则自动匹配字段组、注册嵌入式类型映射,无需逐表逐字段手动配置,可支撑数百张表的批量处理。

前置准备:定义通用嵌入式POJO

首先定义所有同类型嵌入式字段共用的Java值类,示例如下:

public class AmountWithUnit {
    private final Integer amount;
    private final String unit;

    // 全参数构造器、getter方法、equals、hashCode、toString 按需实现即可
    public AmountWithUnit(Integer amount, String unit) {
        this.amount = amount;
        this.unit = unit;
    }

    public Integer getAmount() { return amount; }
    public String getUnit() { return unit; }
}

自定义代码生成器逻辑

继承jOOQ默认的JavaGenerator类,在生成代码前遍历所有表的字段,按你的命名规则自动分组注册嵌入式类型,示例逻辑适配你给出的表结构规则:

import org.jooq.codegen.JavaGenerator;
import org.jooq.meta.*;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class AutoEmbeddableGenerator extends JavaGenerator {
    @Override
    protected void generateSchema(SchemaDefinition schema) {
        // 遍历当前Schema下所有表
        for (TableDefinition table : schema.getTables()) {
            // 过滤所有金额、单位相关字段,按后缀分组
            // 规则:amount、unit为无后缀组,amount_pend、unit_pend为_pend后缀组
            Map<String, List<ColumnDefinition>> embeddableGroups = table.getColumns().stream()
                    .filter(col -> col.getName().matches("^(amount|unit)(_.*)?$"))
                    .collect(Collectors.groupingBy(col -> {
                        String colName = col.getName();
                        return colName.startsWith("amount") 
                                ? colName.replaceFirst("^amount", "") 
                                : colName.replaceFirst("^unit", "");
                    }));

            // 为每个分组注册嵌入式类型
            embeddableGroups.forEach((suffix, columns) -> {
                if (columns.size() == 2) { // 确认分组同时包含amount和unit两个字段
                    EmbeddableDefinition embeddable = new EmbeddableDefinition(
                            schema,
                            table,
                            "AMOUNT_WITH_UNIT" + suffix.toUpperCase(), // 生成的嵌入式字段名
                            columns.stream().map(ColumnDefinition::getName).toList(),
                            AmountWithUnit.class.getName() // 绑定前置定义的通用POJO
                    );
                    table.addEmbeddable(embeddable);
                }
            });
        }
        // 执行默认的代码生成逻辑
        super.generateSchema(schema);
    }
}

配置构建工具使用自定义生成器

以Maven为例,在jOOQ代码生成插件的配置中指定自定义生成器类即可:

<plugin>
    <groupId>org.jooq</groupId>
    <artifactId>jooq-codegen-maven</artifactId>
    <version>你的jOOQ版本号</version>
    <configuration>
        <generator>
            <!-- 替换为你自定义的生成器全类名 -->
            <name>com.yourpackage.AutoEmbeddableGenerator</name>
            <!-- 其余原有配置(数据库连接、生成路径等)保持不变 -->
            <database>
                <!-- 原有数据库配置 -->
            </database>
            <target>
                <!-- 原有生成路径配置 -->
            </target>
        </generator>
    </configuration>
</plugin>

生成效果验证

针对你给出的示例表t:

create table t(amount int, unit varchar2(4), amount_pend int, unit_pend varchar(4));

代码生成后会自动在表类中生成两个嵌入式字段:

  • T.AMOUNT_WITH_UNIT 对应amount+unit字段组
  • T.AMOUNT_WITH_UNIT_PEND 对应amount_pend+unit_pend字段组

你可以直接操作整个嵌入式对象,无需单独处理单个字段:

// 写入示例
ctx.insertInto(T)
        .set(T.AMOUNT_WITH_UNIT, new AmountWithUnit(100, "CNY"))
        .set(T.AMOUNT_WITH_UNIT_PEND, new AmountWithUnit(50, "CNY"))
        .execute();

// 查询示例
AmountWithUnit normalAmount = ctx.select(T.AMOUNT_WITH_UNIT)
        .from(T)
        .fetchOneInto(AmountWithUnit.class);

该方案完全适配批量表场景,只要字段命名规则保持统一,后续新增表、新增同规则嵌入式字段都无需修改配置,自动生成映射。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 18:54:04