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

如何在Spring Boot启动前以编程方式生成jOOQ POJO类?

问题描述

我通过以下代码用jOOQ从数据库生成POJO和记录类:

@Component
public class JooqCodeGenerator implements CommandLineRunner {

  private static final Logger logger = LoggerFactory.getLogger(JooqCodeGenerator.class);

  @Value("${spring.datasource.url}")
  private String url;

  @Value("${spring.datasource.username}")
  private String username;

  @Value("${spring.datasource.password}")
  private String password;

  @Value("${jooq.generator.database.inputSchema}")
  private String inputSchema;

  @Value("${jooq.generator.target.packageName}")
  private String packageName;

  @Value("${jooq.generator.target.directory}")
  private String directory;

  @Override
  public void run(String... args) throws Exception {
    logger.info("Starting jOOQ code generation...");
    Configuration configuration = new Configuration()
        .withJdbc(new Jdbc()
            .withDriver("org.postgresql.Driver")
            .withUrl(url)
            .withUser(username)
            .withPassword(password))
        .withGenerator(new Generator()
            .withDatabase(new Database()
                .withInputSchema(inputSchema)
                .withIncludes(".*")  // Include all tables
                .withExcludes("flyway_schema_history|pg_*"))  // Exclude Flyway and default PostgreSQL tables
            .withTarget(new Target()
                .withPackageName(packageName)
                .withDirectory(directory))
            .withGenerate(new Generate()
                .withDaos(true)
                .withPojos(true)
                .withInterfaces(false)
                .withImmutablePojos(false)
                .withFluentSetters(true)
                .withJavaTimeTypes(true)));

    GenerationTool.generate(configuration);

    logger.info("jOOQ code generation completed.");
  }
}

但在服务和控制器中使用这些生成的类时,运行mvn spring-boot:run会出现编译错误:

[INFO] BUILD FAILURE
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.11.0:compile (default-compile) on project control: Compilation failure: Compilation failure:
[ERROR] ProjectPath/rest/AuditTrailController.java:[3,54] package projectPath.jooq.tables.pojos does not exist

我不想用Maven插件,请问如何让Spring Boot在运行应用前以编程方式生成这些类?

解决方案

问题根源是CommandLineRunner是在Spring应用启动阶段执行的,但Maven的编译阶段(compile)在启动之前就已经完成了,此时生成的类还不存在,导致编译失败。要解决这个问题,需要把代码生成逻辑移到Maven编译阶段之前执行,同时保持编程式的实现方式。

方案1:编写独立Java主类,用Maven exec插件在编译前执行

  1. 把代码生成逻辑从CommandLineRunner中抽出来,写成独立的可执行主类:
public class JooqCodeGeneratorMain {

    private static final Logger logger = LoggerFactory.getLogger(JooqCodeGeneratorMain.class);

    public static void main(String[] args) throws Exception {
        // 读取配置文件
        Properties props = new Properties();
        try (InputStream is = JooqCodeGeneratorMain.class.getClassLoader().getResourceAsStream("application.properties")) {
            props.load(is);
        }

        String url = props.getProperty("spring.datasource.url");
        String username = props.getProperty("spring.datasource.username");
        String password = props.getProperty("spring.datasource.password");
        String inputSchema = props.getProperty("jooq.generator.database.inputSchema");
        String packageName = props.getProperty("jooq.generator.target.packageName");
        String directory = props.getProperty("jooq.generator.target.directory");

        logger.info("Starting jOOQ code generation...");
        Configuration configuration = new Configuration()
                .withJdbc(new Jdbc()
                        .withDriver("org.postgresql.Driver")
                        .withUrl(url)
                        .withUser(username)
                        .withPassword(password))
                .withGenerator(new Generator()
                        .withDatabase(new Database()
                                .withInputSchema(inputSchema)
                                .withIncludes(".*")
                                .withExcludes("flyway_schema_history|pg_*"))
                        .withTarget(new Target()
                                .withPackageName(packageName)
                                .withDirectory(directory))
                        .withGenerate(new Generate()
                                .withDaos(true)
                                .withPojos(true)
                                .withInterfaces(false)
                                .withImmutablePojos(false)
                                .withFluentSetters(true)
                                .withJavaTimeTypes(true)));

        GenerationTool.generate(configuration);
        logger.info("jOOQ code generation completed.");
    }
}
  1. 在pom.xml中配置exec-maven-plugin,让它在compile阶段之前执行这个主类:
<build>
    <plugins>
        <plugin>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>exec-maven-plugin</artifactId>
            <version>3.1.0</version>
            <executions>
                <execution>
                    <id>generate-jooq-classes</id>
                    <phase>generate-sources</phase>
                    <goals>
                        <goal>java</goal>
                    </goals>
                    <configuration>
                        <mainClass>com.yourpackage.JooqCodeGeneratorMain</mainClass>
                    </configuration>
                </execution>
            </executions>
            <dependencies>
                <!-- 引入所需依赖 -->
                <dependency>
                    <groupId>org.jooq</groupId>
                    <artifactId>jooq-codegen</artifactId>
                    <version>${jooq.version}</version>
                </dependency>
                <dependency>
                    <groupId>org.postgresql</groupId>
                    <artifactId>postgresql</artifactId>
                    <version>${postgresql.version}</version>
                </dependency>
                <dependency>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter</artifactId>
                    <version>${spring-boot.version}</version>
                </dependency>
            </dependencies>
        </plugin>
    </plugins>
</build>

这样Maven会在generate-sources阶段执行代码生成,生成的类会被后续的compile阶段识别到。

方案2:自定义Maven生命周期插件(进阶)

如果需要跨项目复用代码生成逻辑,可以编写自定义Maven插件:

  • 创建新的Maven项目,继承maven-plugin
  • 编写Mojo类,在execute()方法中实现jOOQ代码生成逻辑(和之前的生成逻辑一致)
  • 在主项目的pom.xml中引入该插件,绑定到generate-sources阶段

方案3:切换到Gradle构建(如果允许)

Gradle的构建生命周期更灵活,可直接在构建脚本中编写代码生成逻辑:

task generateJooqClasses {
    doLast {
        def props = new Properties()
        file("src/main/resources/application.properties").withInputStream { props.load(it) }

        def configuration = new org.jooq.meta.jaxb.Configuration()
            .withJdbc(new org.jooq.meta.jaxb.Jdbc()
                .withDriver("org.postgresql.Driver")
                .withUrl(props.getProperty("spring.datasource.url"))
                .withUser(props.getProperty("spring.datasource.username"))
                .withPassword(props.getProperty("spring.datasource.password")))
            .withGenerator(new org.jooq.meta.jaxb.Generator()
                .withDatabase(new org.jooq.meta.jaxb.Database()
                    .withInputSchema(props.getProperty("jooq.generator.database.inputSchema"))
                    .withIncludes(".*")
                    .withExcludes("flyway_schema_history|pg_*"))
                .withTarget(new org.jooq.meta.jaxb.Target()
                    .withPackageName(props.getProperty("jooq.generator.target.packageName"))
                    .withDirectory(props.getProperty("jooq.generator.target.directory")))
                .withGenerate(new org.jooq.meta.jaxb.Generate()
                    .withDaos(true)
                    .withPojos(true)
                    .withInterfaces(false)
                    .withImmutablePojos(false)
                    .withFluentSetters(true)
                    .withJavaTimeTypes(true)))

        org.jooq.codegen.GenerationTool.generate(configuration)
    }
}

compileJava.dependsOn(generateJooqClasses)

Gradle会在编译Java代码前先执行generateJooqClasses任务,生成所需类。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 18:05:54