如何构建JOOQ自定义生成器? [英] How build a JOOQ custom generator?

查看:122
本文介绍了如何构建JOOQ自定义生成器?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个特定的Postgre模式,该模式收集定义了类型的所有表,例如 Status(name,description),其中值可以是 OPEN,Open项目状态已关闭,已关闭项目状态,等等。

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.

我们需要提取所有这些表并基于它们生成枚举,以供以后在我们的应用中使用。因此,这些枚举应如下所示:

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

我们决定使用看起来很有趣的JOOQ,但找不到用于创建使用默认Java生成器行为以及自定义枚举生成扩展名的自定义生成器的文档/示例。

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从表中生成枚举类,带来了一些想法,但仍不清楚该怎么做才能达到答案的要求。

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-codegen-maven 插件,我创建了一个单独的项目,并将其jar添加为父项目的依赖项。我创建了一个类 MyGenerator 并将其扩展为 JavaGenerator 。为了拥有这个 org.jooq.codegen.JavaGenerator ,我必须在下面添加maven依赖项(不在 spring-boot-starter-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. I created a class MyGenerator and made it extend from JavaGenerator. In order to have this org.jooq.codegen.JavaGenerator I had to add below maven dependency (not coming in spring-boot-starter-jooq):

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

完成此操作并继承自JavaGenerator,根据发布的答案,我应该加入 generate(SchemaDefinition)方法,但是这不是受保护的范围,所以我认为我在这里丢失了一些东西。

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.

还是可以提供一个示例来描述如何为枚举编写这种代码生成器?我需要JOOQ像往常一样为特定模式生成代码,但除此之外,我还需要查询仅包含那些枚举表的另一个特定枚举模式。

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.

推荐答案

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

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.

该代码是在groovy中实现的,但是对于Java来说却非常相似。

The code was implemented in groovy, but for java it's very similar.

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

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.

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

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

This data definition will result in below autogenerated enum 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;
    }
}






主项目



然后在将要使用此枚举生成器的主项目中,我在 pom.xml

<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自定义生成器?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆