当前位置: 首页 > 知识库问答 >
问题:

如何构建JOOQ定制生成器?

慕阳伯
2023-03-14

我有一个特定的Postgre架构,它收集所有定义类型的表,如状态(名称,描述),其中的值可以是OPEN,打开项状态CLOSED,关闭项状态等。

我们需要获取所有这些表,并根据它们生成枚举,以便以后在我们的应用程序中使用。因此,这些枚举应该如下所示:

enum Status {
    OPEN("Open item status"),
    CLOSED("Closed item status")
    ...
}

我们决定使用JOOQ看起来很有趣,但是我们找不到留档/示例来创建一个使用默认java生成器行为加上自定义枚举生成扩展的自定义生成器。

基于这篇文章用JOOQ从表中生成枚举类,它带来了一些想法,但仍然不清楚如何实现答案的状态。

更新:为了让我的自定义生成器被jooq-codegen-maven插件选中,我创建了一个单独的项目,并添加了它的jar作为我的父项目的依赖项。我创建了一个类MyGenerator,并使其从JavaGenerator扩展。为了让这个org.jooq.codegen.JavaGenerator,我必须在maven依赖项下面添加(没有进入spall-boot-starter-jooq):

<dependency>
    <groupId>org.jooq</groupId>
    <artifactId>jooq-codegen-maven</artifactId>
    <version>3.11.2</version>
</dependency>

一旦这样做,并从JavaGenerator继承,根据后的答案,我应该钩入生成(模式定义)方法,但是这不是受保护的范围,所以我想我在这里错过了一些东西。

你知道或者可以提供一个例子来描述如何为枚举编写这种代码生成器吗?我需要JOOQ像往常一样为特定模式生成代码,但除此之外,我还需要查询另一个只包含那些“enum”表的特定“enum”模式。

共有1个答案

东方宜
2023-03-14

我知道这是一个老生常谈的问题,但我现在发布我的答案,因为它可能对其他人有用。

我不得不面对同样的需求,这很难实现,所以在这里你可以找到我实现的代码,从enums模式生成enum。

这段代码是用groovy实现的,但对java来说非常相似。

首先也是非常重要的一点,我必须为我的枚举生成器创建一个单独的项目,因为它将作为将要使用它的项目的依赖项。这是必需的,因为生成代码的项目必须在编译时运行枚举生成器,所以实现这一点的方法是将枚举生成器添加为依赖项。

package com.ctg.jooqgenerator.jooq

import org.jooq.codegen.JavaGenerator
import org.jooq.codegen.JavaWriter
import org.jooq.meta.Database
import org.jooq.meta.SchemaDefinition
import org.jooq.meta.TableDefinition
import org.slf4j.Logger
import org.slf4j.LoggerFactory

import java.sql.ResultSet

class EnumGenerator extends JavaGenerator {
    private static final String ENUMS_SCHEMA = "enums"

    private static final Logger log = LoggerFactory.getLogger(EnumGenerator.class)

    @Override
    void generateSchema(SchemaDefinition schema) {
        // Apply custom logic only for `enums` schema. Others schema has regular generation
        if (schema.name != ENUMS_SCHEMA) {
            super.generateSchema(schema)
            return
        }

        log.info("Generating enums")
        log.info("----------------------------------------------------------")

        Database db = schema.database

        db.getTables(schema).each { TableDefinition table ->
            // Prepare enum name from snake_case to CamelCase
            String enumName = table.name.replaceAll('_([a-z])') { it[1].capitalize() }.capitalize()

            JavaWriter out = newJavaWriter(new File(getFile(schema).getParentFile(), "${enumName}.java"))
            log.info("Generating enum: {}.java [input={}, output={}]", enumName, table.name, enumName)

            printPackage(out, schema)

            out.println("public enum $enumName {")

            ResultSet rs = db.connection.prepareStatement("SELECT * FROM ${schema}.\"${table.name}\"").executeQuery()
            while (rs.next()) {
                String name = rs.getString('name'),
                       description = rs.getString('description'),
                       s = rs.isLast() ? ";" : ","

                // Generate enum entry
                out.tab(1).println("$name(\"$description\")$s")
            }

            out.println("""
            |    private final String description;
            |
            |    private $enumName(String description) {
            |        this.description = description;
            |    }
            |}
            """.stripMargin())

            closeJavaWriter(out)
        }

        log.info("----------------------------------------------------------")
        super.generateSchema(schema)
    }
}

将被翻译为枚举的表如下所示:

-- Table name `account_role` will be translated into `AccountRole`
CREATE TABLE enums.account_role (
    "name" varchar(100) NOT NULL,
    description varchar(255) NOT NULL,
    CONSTRAINT account_role_name_key UNIQUE (name)
);

-- Table entries will be translated into enum entries
INSERT INTO enums.account_role ("name",description) VALUES 
('BILLING','Role for contact/address that will be a Billing contact/address'),
('PAYMENT','Role for contact/address that will be a Payment contact/address'),
('SERVICE','Role for contact/address that will be a Service contact/address'),
('SOLD_TO','Role for contact/address that will be a SoldTo contact/address')
;

此数据定义将导致以下自动生成的枚举AcCountRole.java:

java prettyprint-override">/*
 * This file is generated by jOOQ.
 */
package com.congerotechnology.ctgcommon.jooq.enums;

public enum AccountRole {
    BILLING("Role for contact/address that will be a Billing contact/address"),
    PAYMENT("Role for contact/address that will be a Payment contact/address"),
    SERVICE("Role for contact/address that will be a Service contact/address"),
    SOLD_TO("Role for contact/address that will be a SoldTo contact/address");

    private final String description;

    private AccountRole(String description) {
        this.description = description;
    }
}

然后在将使用此枚举生成器的主项目上,我在pom.xml上设置了以下maven代码:

<dependencies>
...
    <!-- JOOQ custom generator -->
    <dependency>
       <groupId>com.ctg</groupId>
       <artifactId>ctg-jooq-generator</artifactId>
       <version>0.0.1</version>
    </dependency>
...
</dependencies>

<build>
...
    <plugins>
        <!-- JOOQ code generation -->
        <plugin>
            <groupId>org.jooq</groupId>
            <artifactId>jooq-codegen-maven</artifactId>
            <version>${jooq.version}</version>

            <executions>
                <execution>
                    <id>generate-sources</id>
                    <phase>generate-sources</phase>
                    <goals>
                        <goal>generate</goal>
                    </goals>
                </execution>
            </executions>

            <configuration>
                <jdbc>
                    <driver>org.postgresql.Driver</driver>
                    <url>jdbc:postgresql://${env.DB_URL}</url>
                    <user>${env.DB_USER}</user>
                    <password>${env.DB_PASSWORD}</password>
                </jdbc>
                <generator>
                    <name>com.ctg.ctgjooqgenerator.jooq.EnumGenerator</name>

                    <database>
                        <name>org.jooq.meta.postgres.PostgresDatabase</name>
                        <includes>.*</includes>
                        <excludes />
                        <dateAsTimestamp>true</dateAsTimestamp>
                        <inputSchema>enums</inputSchema>
                    </database>
                    <generate>
                        <deprecated>false</deprecated>
                        <instanceFields>true</instanceFields>
                    </generate>
                    <target>
                        <packageName>com.ctg.ctgcommon.jooq.enums</packageName>
                        <directory>target/generated-sources/jooq-postgres</directory>
                    </target>
                </generator>
            </configuration>

            <dependencies>
                <dependency>
                    <groupId>org.postgresql</groupId>
                    <artifactId>postgresql</artifactId>
                    <version>${postgresql.version}</version>
                </dependency>
            </dependencies>
        </plugin>
    </plugins>
 类似资料:
  • 我更改了数据库中的一些表,所以我想生成记录、键、类等。但是每次我这样做时,它总是跳过jooq代码生成。 [INFO]--jooq-codegen-maven:3.11.10:generate(默认cli)@http网关--[INFO]跳过jooq代码生成 为了运行Jooq代码生成,我应该执行哪个mvn cmd?现在我使用: 谢谢

  • MySQL不接受此处生成的datetime值。我探索并发现jOOQ转换器可以用于自定义转换。我可以找到如何在获取数据时使用转换的示例,但无法弄清楚如何在查询时使用转换器。如何使用jOOQ转换器生成SQL而不生成代码?或者是否有更好的方法为SQL生成此查询。

  • 我有一个有许多表的数据库。我想开始使用jOOQ为我的应用程序。但是我不希望JOOQ为所有表生成代码,但只为表的一小部分生成代码。我如何配置它?

  • 我使用jOOQ程序代码生成数据库,但现在我遇到了一些问题。在数据库中,我有表A和表B。第一次都生成了pojo、dao、接口等。经过一段时间的开发,我发现表A需要添加一些字段或修改一些字段,所以我不得不再次编码,然后jOOQ代码生成器将覆盖现有的代码,这让我很难过。当我在排除表的情况下使用“排除A”时,发现只生成了表A的数据,表B将被删除。我不知道如何处理这个问题。我的代码生成器如下:

  • 问题内容: 我正在尝试将jOOQ包含在我的代码中,但是未生成任何代码。 执行时,不会生成任何源。我希望它创建一个在以下-file文件中定义的类。 我的pom.xml文件如下所示: 我假设应该使用适当的类来创建目录。Maven构建成功运行,没有任何错误。 您可以在此GitHub存储库中找到整个项目。 问题答案: 您正在使用内存数据库:。jOOQ代码生成器启动时,它将接收到一个空的 新 数据库,而不是

  • 问题 在代码生成期间,我在配置到自定义POJO的映射时遇到了一些问题。 问题 我已经实现了,但想知道如何注册它以在代码生成阶段使用,或者即使这是可能的? 更多上下文 我喜欢波霍斯 如果有帮助,我将使用DefaultConfiguration对象(一个bean)配置jOOQ: 然后对于代码生成,我在gradle中配置它: 我确信这两种配置之间存在脱节,但我无法从文档中了解如何同步这些配置。理想情况下