可用版本:Dev (3.21) | 最新 (3.20) | 3.19 | 3.18 | 3.17 | 3.16 | 3.15 | 3.14 | 3.13 | 3.12 | 3.11

自定义生成器策略

适用于 ✅ 开源版   ✅ 专业版   ✅ 企业版

使用自定义生成器策略来覆盖命名方案

jOOQ 允许您覆盖代码生成器或生成器策略的默认实现。特别是,如果您想将自定义行为注入到 jOOQ 的代码生成器中,以命名类、成员、方法和其他 Java 对象,后者会非常有用。

XML(独立和 Maven)
编程方式
Gradle (Kotlin)
Gradle (Groovy)
Gradle(第三方)
<configuration>
  <generator>

    <!-- A programmatic naming strategy implementation, referened by class name. -->
    <strategy>
      <name>com.example.AsInDatabaseStrategy</name>
    </strategy>
  </generator>
</configuration>

有关更多详细信息,请参阅 配置 XSD独立代码生成maven 代码生成

new org.jooq.meta.jaxb.Configuration()
  .withGenerator(new Generator()

    // A programmatic naming strategy implementation, referened by class name.
    .withStrategy(new Strategy()
      .withName("com.example.AsInDatabaseStrategy")
    )
  )

有关更多详细信息,请参阅 配置 XSD编程代码生成

import org.jooq.meta.jaxb.*


configuration {
  generator {

    // A programmatic naming strategy implementation, referened by class name.
    strategy {
      name = "com.example.AsInDatabaseStrategy"
    }
  }
}

有关更多详细信息,请参阅 配置 XSDgradle 代码生成

configuration {
  generator {

    // A programmatic naming strategy implementation, referened by class name.
    strategy {
      name = "com.example.AsInDatabaseStrategy"
    }
  }
}

有关更多详细信息,请参阅 配置 XSDgradle 代码生成

// The jOOQ-codegen-gradle plugin has been introduced in version 3.19.
// Please use the official plugin instead of the third party plugin that was recommended before.

或者,您可以选择将策略代码(用 Java 编写)内联到配置中,而不是引用先前编译的 GeneratorStrategy,在这种情况下,它将被临时编译(有关更多详细信息,请参阅内存编译

XML(独立和 Maven)
编程方式
Gradle (Kotlin)
Gradle (Groovy)
Gradle(第三方)
<configuration>
  <generator>

    <!-- A programmatic naming strategy implementation, referened by class name. -->
    <strategy>
      <name>com.example.AsInDatabaseStrategy</name>
      <java>package com.example;

import org.jooq.codegen.DefaultGeneratorStrategy;

public class AsInDatabaseStrategy extends DefaultGeneratorStrategy {
    ...
}</java>
    </strategy>
  </generator>
</configuration>

有关更多详细信息,请参阅 配置 XSD独立代码生成maven 代码生成

new org.jooq.meta.jaxb.Configuration()
  .withGenerator(new Generator()

    // A programmatic naming strategy implementation, referened by class name.
    .withStrategy(new Strategy()
      .withName("com.example.AsInDatabaseStrategy")
      .withJava("""package com.example;

import org.jooq.codegen.DefaultGeneratorStrategy;

public class AsInDatabaseStrategy extends DefaultGeneratorStrategy {
    ...
}""")
    )
  )

有关更多详细信息,请参阅 配置 XSD编程代码生成

import org.jooq.meta.jaxb.*


configuration {
  generator {

    // A programmatic naming strategy implementation, referened by class name.
    strategy {
      name = "com.example.AsInDatabaseStrategy"
      java = """package com.example;

import org.jooq.codegen.DefaultGeneratorStrategy;

public class AsInDatabaseStrategy extends DefaultGeneratorStrategy {
    ...
}"""
    }
  }
}

有关更多详细信息,请参阅 配置 XSDgradle 代码生成

configuration {
  generator {

    // A programmatic naming strategy implementation, referened by class name.
    strategy {
      name = "com.example.AsInDatabaseStrategy"
      java = """package com.example;

import org.jooq.codegen.DefaultGeneratorStrategy;

public class AsInDatabaseStrategy extends DefaultGeneratorStrategy {
    ...
}"""
    }
  }
}

有关更多详细信息,请参阅 配置 XSDgradle 代码生成

// The jOOQ-codegen-gradle plugin has been introduced in version 3.19.
// Please use the official plugin instead of the third party plugin that was recommended before.
请确保您的自定义生成器策略及其依赖项作为代码生成器依赖项对代码生成器可用

以下示例展示了如何覆盖 DefaultGeneratorStrategy 以按照数据库中的定义方式呈现表名和列名,而不是将它们切换为驼峰式命名

/**
 * It is recommended that you extend the DefaultGeneratorStrategy. Most of the
 * GeneratorStrategy API is already declared final. You only need to override any
 * of the following methods, for whatever generation behaviour you'd like to achieve.
 *
 * Also, the DefaultGeneratorStrategy takes care of disambiguating quite a few object
 * names in case of conflict. For example, MySQL indexes do not really have a name, so
 * a synthetic, non-ambiguous name is generated based on the table name. If you
 * override the default behaviour, you must ensure that this disambiguation still takes
 * place for generated code to be compilable.
 *
 * Beware that most methods also receive a "Mode" object, to tell you whether a
 * TableDefinition is being rendered as a Table, Record, POJO, etc. Depending on
 * that information, you can add a suffix only for TableRecords, but not for Tables,
 * for example.
 *
 * This example will name objects in Java as they are named in the database, without
 * applying any camelCase, PascalCase transformations, etc.
 */
public class AsInDatabaseStrategy extends DefaultGeneratorStrategy {

    /**
     * Override this to specify what identifiers, such as Catalog, Schema, Table, 
     * TableField identifiers will look like.
     *
     * This example will just generate the identifier as defined in the database,
     * e.g. MY_TABLE or MY_TABLE.MY_FIELD.
     */
    @Override
    public String getJavaIdentifier(Definition definition) {
        // The DefaultGeneratorStrategy disambiguates some synthetic object names,
        // such as the MySQL PRIMARY key names, which do not really have a name
        // Uncomment the below code if you want to reuse that logic.
        // if (definition instanceof IndexDefinition)
        //     return super.getJavaIdentifier(definition);
        return definition.getOutputName();
    }

    /**
     * Override these to specify what a setter in Java should look like. Setters
     * are used in TableRecords, UDTRecords, and POJOs, depending on Mode.
     *
     * This example will name setters "set[NAME_IN_DATABASE]"
     */
    @Override
    public String getJavaSetterName(Definition definition, Mode mode) {
        return "set" + definition.getOutputName();
    }

    /**
     * Override these to specify what a getter in Java should look like. Getters
     * are used in TableRecords, UDTRecords, and POJOs, depending on Mode. 
     *
     * This example will name getters "set[NAME_IN_DATABASE]"
     */
    @Override
    public String getJavaGetterName(Definition definition, Mode mode) {
        return "get" + definition.getOutputName();
    }

    /**
     * Override this method to define what a Java method generated from a database
     * Definition should look like. This is used e.g. for convenience methods
     * when calling stored procedures and functions, or for path methods.
     *
     * This example shows how to set a prefix to a CamelCase version of your
     * procedure.
     */
    @Override
    public String getJavaMethodName(Definition definition, Mode mode) {
        if (definition instanceof RoutineDefinition)
            return "call" + org.jooq.tools.StringUtils.toCamelCase(definition.getOutputName());
        else
            return super.getJavaMethodName(definition, mode);
    }

    /**
     * Override this method to define how your Java classes and Java files should
     * be named.
     * 
     * This example applies no custom setting and uses CamelCase versions instead.
     */
    @Override
    public String getJavaClassName(Definition definition, Mode mode) {
        return super.getJavaClassName(definition, mode);
    }

    /**
     * Override this method to re-define the package names of your generated
     * artefacts.
     */
    @Override
    public String getJavaPackageName(Definition definition, Mode mode) {
        return super.getJavaPackageName(definition, mode);
    }

    /**
     * Override this method to define how Java members should be named. This is
     * used for POJO members and method arguments, for example, or when using the
     * KotlinGenerator or ScalaGenerator also for record or interface properties.
     */
    @Override
    public String getJavaMemberName(Definition definition, Mode mode) {
        return definition.getOutputName();
    }

    /**
     * Override this method to define the base class for those artefacts that
     * allow for custom base classes. Your custom base class should extend the
     * internal default base class (e.g. TableImpl, UpdatableRecordImpl, etc.)
     * for best results.
     *
     * This example provides a custom extension of the org.jooq.TableImpl class.
     */
    @Override
    public String getJavaClassExtends(Definition definition, Mode mode) {
        if (definition instanceof TableDefinition && mode == Mode.DEFAULT)
            return MyBaseTableImpl.class.getName();
        else
            return super.getJavaClassExtends(definition, mode);
    }

    /**
     * Override this method to define the interfaces to be implemented by those
     * artefacts that allow for custom interface implementation.
     *
     * This example adds serialisability and cloneability to all generated classes.
     */
    @Override
    public List<String> getJavaClassImplements(Definition definition, Mode mode) {
        return Arrays.asList(Serializable.class.getName(), Cloneable.class.getName());
    }

    /**
     * Override this method to define the suffix to apply to routines when
     * they are overloaded.
     *
     * Use this to resolve compile-time conflicts in generated source code, in
     * case you make heavy use of procedure overloading
     */
    @Override
    public String getOverloadSuffix(Definition definition, Mode mode, String overloadIndex) {
        return "_OverloadIndex_" + overloadIndex;
    }
}

org.jooq.Table 示例

这是一个示例,展示了在生成表时将在什么位置调用哪些生成器策略方法。为了提高可读性,省略了完整限定名

package com.example.tables;
//   1: ^^^^^^^^^^^^^^^^^^
public class Book extends TableImpl<com.example.tables.records.BookRecord> {
//        2: ^^^^                                           3: ^^^^^^^^^^
    public static final Book    BOOK = new Book();
//                   2: ^^^^ 4: ^^^^
    public final TableField<BookRecord, Integer> ID = /* ... */
//                       3: ^^^^^^^^^^        5: ^^
}

// 1: strategy.getJavaPackageName(table)
// 2: strategy.getJavaClassName(table)
// 3: strategy.getJavaClassName(table, Mode.RECORD)
// 4: strategy.getJavaIdentifier(table)
// 5: strategy.getJavaIdentifier(column)

org.jooq.Record 示例

这是一个示例,展示了在生成记录时将在什么位置调用哪些生成器策略方法。为了提高可读性,省略了完整限定名

package com.example.tables.records;
//   1: ^^^^^^^^^^^^^^^^^^^^^^^^^^
public class BookRecord extends UpdatableRecordImpl<BookRecord> {
//        2: ^^^^^^^^^^                          2: ^^^^^^^^^^
    public void setId(Integer value) { /* ... */ }
//           3: ^^^^^
    public Integer getId() { /* ... */ }
//              4: ^^^^^
}

// 1: strategy.getJavaPackageName(table, Mode.RECORD)
// 2: strategy.getJavaClassName(table, Mode.RECORD)
// 3: strategy.getJavaSetterName(column, Mode.RECORD)
// 4: strategy.getJavaGetterName(column, Mode.RECORD)

POJO 示例

这是一个示例,展示了在生成 pojo 时将在什么位置调用哪些生成器策略方法。为了提高可读性,省略了完整限定名

package com.example.tables.pojos;
//   1: ^^^^^^^^^^^^^^^^^^^^^^^^
public class Book implements java.io.Serializable {
//        2: ^^^^
    private Integer id;
//               3: ^^
    public void setId(Integer value) { /* ... */ }
//           4: ^^^^^
    public Integer getId() { /* ... */ }
//              5: ^^^^^

}

// 1: strategy.getJavaPackageName(table, Mode.POJO)
// 2: strategy.getJavaClassName(table, Mode.POJO)
// 3: strategy.getJavaMemberName(column, Mode.POJO)
// 4: strategy.getJavaSetterName(column, Mode.POJO)
// 5: strategy.getJavaGetterName(column, Mode.POJO)

开箱即用的策略

jooq-codegen 模块提供了以下开箱即用的策略,可以直接使用,也可以作为灵感来源

  • org.jooq.codegen.KeepNamesGeneratorStrategy:完全按照名称和标识符在数据库中的形式保留所有名称和标识符,包括大小写和下划线。即,snake_case 标识符将生成 snake_case 类和成员,而 PascalCase 标识符将生成 PascalCase 类和成员。
  • org.jooq.codegen.PascalCaseGeneratorStrategy:将所有 snake_case(小写和大写)标识符转换为 PascalCase,同时保持 PascalCase 标识符不变。这在通常以 PascalCase 定义标识符的 T-SQL 样式架构中非常理想。

更多示例可以在这里找到

反馈

您对此页面有任何反馈吗?我们很乐意倾听!

The jOOQ Logo