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

如何通过jOOQ生成器将数据库表、列名映射为易读名称?

问题描述

我有一个遗留数据库,表和列名如下:
XYZEMP:

  • XYZCMP
  • XYZUSR
  • XYZNME

希望映射为易读名称:
EMPLOYEE:

  • COMPANY
  • USERNAME
  • NAME

使用标准jOOQ代码生成器时,会生成XYZEMP表对象、XyzempRecord等,列名仍为XYZCMP这类缩写,对应的getter/setter也沿用原名称。请问能否通过传递映射规则给生成器,让它生成Employee表对象、EmployeeRecord以及易读的列名?

我的思路是使用自定义生成器策略,示例代码如下:

public class AsInDatabaseStrategy extends DefaultGeneratorStrategy {
    @Override
    public String getJavaClassName(Definition definition, Mode mode) {
        Map<String, String> tableNamesMapping = readTableNames();
        if (mode == Mode.DEFAULT){ //for table class
             String readableName = tableNamesMapping.get(definition.getOutputName());
             if (readableName == null){
               throw new IllegalStateException("Table " + definition.getOutputName() + " lacks mapping");
             }
             return readableName;
        } else if (mode == Mode.RECORD) { // for record
            // similar logic for record
            return readableName + "Record";
        }
        return super.getJavaClassName(definition, mode);
    }
    @Override
    public String getJavaIdentifier(Definition definition) {
    // somehow similar code for table and and column
    }
    @Override
    public String getJavaSetterName(Definition definition, Mode mode) {
    // somehow similar code for table and and column
    }
    @Override
    public String getJavaGetterName(Definition definition, Mode mode) {
    // somehow similar code for table and and column
    }
    private Map<String, String> readTableNames(){
    //read names mapping from file
    }
    private Map<String, Map<String, String>> readColumnNames(){
    //read names mapping from file
    }
}

映射文件分为表映射:

{
"XYZEMP" : "EMPLOYEE",
...
}

和列映射:

{
"XYZEMP" : {
"XYZCMP" : "COMPANY",
"XYZUSR" : "USERNAME",
"XYZNME" : "NAME"
}
...
}

请问有没有更优的实现方式?另外在我的方案中,如何通过Definition对象区分表/列(或其他对象),以及如何获取列所属的表?


解决方案

1. 更优实现方式

你的自定义生成器策略思路是可行的,以下是几个优化方向:

(1)复用内置策略逻辑

不用完全重写所有方法,DefaultGeneratorStrategy已经提供了驼峰转换等命名规范处理逻辑,可以在映射后的名称基础上调用父类方法做规范处理。比如映射得到EMPLOYEE后,父类会自动转成Employee作为类名,避免手动处理大小写。

(2)使用配置式映射(无需编写自定义类)

jOOQ 3.14+支持在代码生成XML配置中直接定义映射规则,无需编写自定义Java类,维护成本更低,适合规则固定的场景:

<generator>
  <database>
    <name>org.jooq.meta.postgres.PostgresDatabase</name>
    <!-- 表名与记录类名映射 -->
    <tables>
      <table>
        <inputName>XYZEMP</inputName>
        <outputName>EMPLOYEE</outputName>
        <recordName>EmployeeRecord</recordName>
        <!-- 列名映射 -->
        <fields>
          <field>
            <inputName>XYZCMP</inputName>
            <outputName>COMPANY</outputName>
          </field>
          <field>
            <inputName>XYZUSR</inputName>
            <outputName>USERNAME</outputName>
          </field>
          <field>
            <inputName>XYZNME</inputName>
            <outputName>NAME</outputName>
          </field>
        </fields>
      </table>
    </tables>
  </database>
</generator>

如果映射规则需要动态加载(比如从外部配置文件读取),再使用自定义策略方案更合适。

(3)缓存映射规则

你的readTableNames()和readColumnNames()方法每次调用都会读取文件,建议在策略类初始化时一次性加载并缓存映射规则,避免重复IO操作。

2. 区分Definition类型与获取列所属表

(1)区分表/列等对象类型

Definition是所有数据库对象的父接口,可以通过instanceof判断具体类型:

// 判断是否为表
if (definition instanceof TableDefinition) {
    // 处理表逻辑
} 
// 判断是否为列
else if (definition instanceof ColumnDefinition) {
    // 处理列逻辑
}
// 其他类型(如索引、约束)可类似判断
else if (definition instanceof IndexDefinition) {
    // 处理索引逻辑
}

(2)获取列所属的表

ColumnDefinition提供了getTable()方法,可直接获取所属表的TableDefinition:

if (definition instanceof ColumnDefinition colDef) {
    TableDefinition tableDef = colDef.getTable();
    String originalTableName = tableDef.getOutputName(); // 获取原表名,用于查找列映射
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 22:17:07