简体   繁体   English

如何构建 JOOQ 自定义生成器?

[英]How build a JOOQ custom generator?

I have a specific Postgre schema that gathers all tables that defines types, like Status(name, description) where values could be OPEN, Open item status , CLOSED, Closed item status , etc.我有一个特定的 Postgre 模式,它收集所有定义类型的表,比如Status(name, description) ,其中的值可以是OPEN, Open item statusCLOSED, Closed item status等。

We need to fetch all these tables and generate enums based on them to later use it within our app.我们需要获取所有这些表并基于它们生成枚举,以便稍后在我们的应用程序中使用它。 So, these enums should look like:因此,这些枚举应如下所示:

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

We decided to use JOOQ which looks pretty interesting, but we cannot find documentation/examples to create a custom generator that use default java generator behavior plus a custom enum generation extension.我们决定使用看起来很有趣的 JOOQ,但我们找不到文档/示例来创建使用默认 java 生成器行为和自定义枚举生成扩展的自定义生成器。

Basing on this post generate enum class from table with JOOQ , it brought some ideas but still not clear what to do to achieve what the answer states.基于这篇文章,使用 JOOQ 从表中生成枚举类,它带来了一些想法,但仍然不清楚如何实现答案所述的内容。

Update: in order to have my custom generator to being picked by jooq-codegen-maven plugin I created a separate project and added its jar as a dependency of my parent project.更新:为了让jooq-codegen-maven插件选择我的自定义生成器,我创建了一个单独的项目并将其 jar 添加为我的父项目的依赖项。 I created a class MyGenerator and made it extend from JavaGenerator .我创建了一个类MyGenerator并使其从JavaGenerator扩展。 In order to have this org.jooq.codegen.JavaGenerator I had to add below maven dependency (not coming in spring-boot-starter-jooq ):为了拥有这个org.jooq.codegen.JavaGenerator我必须添加以下 maven 依赖项(不在spring-boot-starter-jooq ):

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

Once done this and inherited from JavaGenerator, according to the post answer I should hook into generate(SchemaDefinition) method, however this is not protected scope, so I think I'm missing something here.完成此操作并从 JavaGenerator 继承后,根据帖子答案,我应该挂钩generate(SchemaDefinition)方法,但是这不是受保护的范围,所以我想我在这里遗漏了一些东西。

Do you know or can you provide an example describing how to write this kind of code generator for enums?你知道或者你能提供一个例子来描述如何为枚举编写这种代码生成器吗? I need JOOQ to generate code as usual for a specific schema, but besides it I need to query another specific "enum" schema that only contains those "enum" tables.我需要 JOOQ 像往常一样为特定模式生成代码,但除此之外,我需要查询另一个仅包含那些“枚举”表的特定“枚举”模式。

I know this is an old question, but I'm posting my answer since it might be useful for others.我知道这是一个老问题,但我发布了我的答案,因为它可能对其他人有用。

I had to face the same needs and it was very difficult to achieve, so here you can find the code I implemented to generate enums from an enums schema.我不得不面对同样的需求并且很难实现,所以在这里你可以找到我实现的代码,用于从enums模式生成枚举。

The code was implemented in groovy, but for java it's very similar.代码是在 groovy 中实现的,但对于 java 来说非常相似。

First and very important , I had to create a separate project for my enum generator since it will work as a dependency for the project that is going to use it.首先,非常重要的是,我必须为我的枚举生成器创建一个单独的项目,因为它将作为将要使用它的项目的依赖项。 This is needed because the project generating the code must run the enum generator at compilation time, so the way to achieve this is by adding the enum generator as a dependency.这是必需的,因为生成代码的项目必须在编译时运行 enum 生成器,因此实现这一点的方法是添加 enum 生成器作为依赖项。

Enum generator project dependency枚举生成器项目依赖

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)
    }
}

Database having enum tables具有枚举表的数据库

The tables that will be translated to enums look like this:将被转换为枚举的表如下所示:

-- 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')
;

This data definition will result in below autogenerated enum AccountRole.java:此数据定义将导致以下自动生成的枚举 AccountRole.java:

/*
 * 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;
    }
}

Main project主要项目

Then on the main project that is going to use this enum generator I have set the following maven code on pom.xml :然后在将要使用这个枚举生成器的主项目上,我在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>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM