自定义复合用户类型通过 JPADatabase 问题生成 JOOQ 代码

JOOQ Code Generation via JPADatabase problem with custom composite user type

我正在尝试使用 JPA 实体的 JOOQ 代码生成。我已经创建了一个专用的 maven 模块,其中将生成代码,它依赖于包含所有实体的模块以及带有 jooq 的代码生成插件。

为了进一步说明项目结构,这里是模块:(名称是虚构的,但结构反映了我正在处理的当前项目)

net-example
  |- net-example-data (contains both entities and spring data repositories)
  |- net-example-jooq (where jooq plugin below is configured and should generate the code )
  |- net-example-business (business layer)
  |- net-example-api (api layer)

所以最后我想要的是,当我构建 net-example-jooq 时,它应该能够从 net-example-data 中找到的实体生成 jooq 类。

pom.xml of net-example-jooq

<build>
        .....
        <plugins>
            <plugin>
                <groupId>org.jooq</groupId>
                <artifactId>jooq-codegen-maven</artifactId>
                <version>${jooq.version}</version>
                <!-- The plugin should hook into the generate goal -->
                <executions>
                    <execution>
                        <goals>
                            <goal>generate</goal>
                        </goals>

                    </execution>
                </executions>
                <!-- Specify the plugin configuration.
                     The configuration format is the same as for the standalone code generator -->
                <configuration>
                    <!-- Generator parameters -->
                    <generator>
                        <database>
                            <name>org.jooq.meta.extensions.jpa.JPADatabase</name>
                            <properties>
                                <property>
                                    <key>packages</key>
                                    <value>net.example</value>
                                </property>
                                <property>
                                    <key>useAttributeConverters</key>
                                    <value>true</value>
                                </property>
                                <property>
                                    <key>unqualifiedSchema</key>
                                    <value>none</value>
                                </property>
                                <property>
                                    <key>hibernate.physical_naming_strategy</key>
                                    <value>org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy</value>
                                </property>
                            </properties>
                            <customTypes>
                                <customType>
                                    <name>money-type</name>
                                    <type>org.javamoney.moneta.Money</type>
                                </customType>
                                <customType>
                                    <name>currency-unit-type</name>
                                    <type>javax.money.CurrencyUnit</type>
                                </customType>
                                <customType>
                                    <name>zone-id-type</name>
                                </customType>
                            </customTypes>
                        </database>
                        <target>
                            <packageName>net.example.generated</packageName>
                            <directory>src/main/java</directory>
                        </target>
                    </generator>
                </configuration>
                <dependencies>
                    <dependency>
                        <groupId>com.h2database</groupId>
                        <artifactId>h2</artifactId>
                        <version>1.4.193</version>
                    </dependency>
                    <dependency>
                        <groupId>org.springframework.boot</groupId>
                        <artifactId>spring-boot-starter-data-jpa</artifactId>
                        <version>2.3.5.RELEASE</version>
                    </dependency>
                    <dependency>
                        <groupId>net.example</groupId>
                        <artifactId>example-data</artifactId>
                        <version>${project.version}</version>
                    </dependency>
                </dependencies>
            </plugin>
        </plugins>
...

这是包含自定义类型的实体之一。

@Entity
public class Example {

   @Id
   private UUID id;
   
   @Column(name = "NAME")
   private String name;


   @Columns(columns = {
            @Column(name = "CURRENCY"),
            @Column(name = "AMOUNT")
    })
    private Money moneyAmount; // org.javamoney.moneta.Money 

   ....

}

自定义类型使用 package.info

定义
@TypeDef(name = "money-type", typeClass = PersistentMoneyAmountAndCurrency.class, defaultForType = Money.class)
@TypeDef(name = "currency-unit-type", typeClass = PersistentCurrencyUnit.class, defaultForType = CurrencyUnit.class)
@TypeDef(name = "zone-id-type", typeClass = PersistentZoneIdAsString.class, defaultForType = ZoneId.class)
package net.example.data;

当我运行 mvn 从根目录(包括数据模块、jooq 模块和其他模块)编译项目时,我在构建 jooq 模块时遇到以下错误。

...
[ERROR] Failed to execute goal org.jooq:jooq-codegen-maven:3.14.8:generate (default) on project enmacc-server-jooq: Error running jOOQ code generation tool: Error while exporting schema: Could not determine type for column moneyAmount of type org.hibernate.type.SerializableType: java.lang.ArrayIndexOutOfBoundsException: Array index out of range: 1 -> [Help 1]
org.apache.maven.lifecycle.LifecycleExecutionException: Failed to execute goal org.jooq:jooq-codegen-maven:3.14.8:generate (default) on project enmacc-server-jooq: Error running jOOQ code generation tool
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:215)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:156)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:148)
    at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject (LifecycleModuleBuilder.java:117)
    at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject (LifecycleModuleBuilder.java:81)
    at org.apache.maven.lifecycle.internal.builder.singlethreaded.SingleThreadedBuilder.build (SingleThreadedBuilder.java:56)
    at org.apache.maven.lifecycle.internal.LifecycleStarter.execute (LifecycleStarter.java:128)
    at org.apache.maven.DefaultMaven.doExecute (DefaultMaven.java:305)
    at org.apache.maven.DefaultMaven.doExecute (DefaultMaven.java:192)
    at org.apache.maven.DefaultMaven.execute (DefaultMaven.java:105)
    at org.apache.maven.cli.MavenCli.execute (MavenCli.java:957)
    at org.apache.maven.cli.MavenCli.doMain (MavenCli.java:289)
    at org.apache.maven.cli.MavenCli.main (MavenCli.java:193)
    at sun.reflect.NativeMethodAccessorImpl.invoke0 (Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke (NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke (DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke (Method.java:498)
    at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced (Launcher.java:282)
    at org.codehaus.plexus.classworlds.launcher.Launcher.launch (Launcher.java:225)
    at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode (Launcher.java:406)
    at org.codehaus.plexus.classworlds.launcher.Launcher.main (Launcher.java:347)
Caused by: org.apache.maven.plugin.MojoExecutionException: Error running jOOQ code generation tool
    at org.jooq.codegen.maven.Plugin.execute (Plugin.java:210)
    at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo (DefaultBuildPluginManager.java:137)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:210)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:156)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:148)
    at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject (LifecycleModuleBuilder.java:117)
    at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject (LifecycleModuleBuilder.java:81)
    at org.apache.maven.lifecycle.internal.builder.singlethreaded.SingleThreadedBuilder.build (SingleThreadedBuilder.java:56)
    at org.apache.maven.lifecycle.internal.LifecycleStarter.execute (LifecycleStarter.java:128)
    at org.apache.maven.DefaultMaven.doExecute (DefaultMaven.java:305)
    at org.apache.maven.DefaultMaven.doExecute (DefaultMaven.java:192)
    at org.apache.maven.DefaultMaven.execute (DefaultMaven.java:105)
    at org.apache.maven.cli.MavenCli.execute (MavenCli.java:957)
    at org.apache.maven.cli.MavenCli.doMain (MavenCli.java:289)
    at org.apache.maven.cli.MavenCli.main (MavenCli.java:193)
    at sun.reflect.NativeMethodAccessorImpl.invoke0 (Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke (NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke (DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke (Method.java:498)
    at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced (Launcher.java:282)
    at org.codehaus.plexus.classworlds.launcher.Launcher.launch (Launcher.java:225)
    at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode (Launcher.java:406)
    at org.codehaus.plexus.classworlds.launcher.Launcher.main (Launcher.java:347)
Caused by: org.jooq.exception.DataAccessException: Error while exporting schema
    at org.jooq.meta.extensions.AbstractInterpretingDatabase.connection (AbstractInterpretingDatabase.java:103)
    at org.jooq.meta.extensions.AbstractInterpretingDatabase.create0 (AbstractInterpretingDatabase.java:77)
    at org.jooq.meta.AbstractDatabase.create (AbstractDatabase.java:296)
    at org.jooq.meta.AbstractDatabase.create (AbstractDatabase.java:285)
    at org.jooq.meta.AbstractDatabase.setConnection (AbstractDatabase.java:275)
    at org.jooq.codegen.GenerationTool.run0 (GenerationTool.java:532)
    at org.jooq.codegen.GenerationTool.run (GenerationTool.java:233)
    at org.jooq.codegen.GenerationTool.generate (GenerationTool.java:228)
    at org.jooq.codegen.maven.Plugin.execute (Plugin.java:207)
    at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo (DefaultBuildPluginManager.java:137)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:210)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:156)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:148)
    at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject (LifecycleModuleBuilder.java:117)
    at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject (LifecycleModuleBuilder.java:81)
    at org.apache.maven.lifecycle.internal.builder.singlethreaded.SingleThreadedBuilder.build (SingleThreadedBuilder.java:56)
    at org.apache.maven.lifecycle.internal.LifecycleStarter.execute (LifecycleStarter.java:128)
    at org.apache.maven.DefaultMaven.doExecute (DefaultMaven.java:305)
    at org.apache.maven.DefaultMaven.doExecute (DefaultMaven.java:192)
    at org.apache.maven.DefaultMaven.execute (DefaultMaven.java:105)
    at org.apache.maven.cli.MavenCli.execute (MavenCli.java:957)
    at org.apache.maven.cli.MavenCli.doMain (MavenCli.java:289)
    at org.apache.maven.cli.MavenCli.main (MavenCli.java:193)
    at sun.reflect.NativeMethodAccessorImpl.invoke0 (Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke (NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke (DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke (Method.java:498)
    at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced (Launcher.java:282)
    at org.codehaus.plexus.classworlds.launcher.Launcher.launch (Launcher.java:225)
    at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode (Launcher.java:406)
    at org.codehaus.plexus.classworlds.launcher.Launcher.main (Launcher.java:347)
Caused by: org.hibernate.MappingException: Could not determine type for column minimum_price_fluctuation_amount of type org.hibernate.type.SerializableType: java.lang.ArrayIndexOutOfBoundsException
    at org.hibernate.mapping.Column.getSqlTypeCode (Column.java:213)
    at org.hibernate.mapping.Column.getSqlType (Column.java:238)
    at org.hibernate.tool.schema.internal.StandardTableExporter.getSqlCreateStrings (StandardTableExporter.java:96)
    at org.hibernate.tool.schema.internal.StandardTableExporter.getSqlCreateStrings (StandardTableExporter.java:30)
    at org.hibernate.tool.schema.internal.SchemaCreatorImpl.createFromMetadata (SchemaCreatorImpl.java:315)
    at org.hibernate.tool.schema.internal.SchemaCreatorImpl.performCreation (SchemaCreatorImpl.java:166)
    at org.hibernate.tool.schema.internal.SchemaCreatorImpl.doCreation (SchemaCreatorImpl.java:135)
    at org.hibernate.tool.schema.internal.SchemaCreatorImpl.doCreation (SchemaCreatorImpl.java:121)
    at org.hibernate.tool.hbm2ddl.SchemaExport.doExecution (SchemaExport.java:296)
    at org.hibernate.tool.hbm2ddl.SchemaExport.execute (SchemaExport.java:249)
    at org.hibernate.tool.hbm2ddl.SchemaExport.execute (SchemaExport.java:228)
    at org.hibernate.tool.hbm2ddl.SchemaExport.create (SchemaExport.java:220)
    at org.jooq.meta.extensions.jpa.JPADatabase.export (JPADatabase.java:156)
    at org.jooq.meta.extensions.AbstractInterpretingDatabase.connection (AbstractInterpretingDatabase.java:100)
    at org.jooq.meta.extensions.AbstractInterpretingDatabase.create0 (AbstractInterpretingDatabase.java:77)
    at org.jooq.meta.AbstractDatabase.create (AbstractDatabase.java:296)
    at org.jooq.meta.AbstractDatabase.create (AbstractDatabase.java:285)
    at org.jooq.meta.AbstractDatabase.setConnection (AbstractDatabase.java:275)
    at org.jooq.codegen.GenerationTool.run0 (GenerationTool.java:532)
    at org.jooq.codegen.GenerationTool.run (GenerationTool.java:233)
    at org.jooq.codegen.GenerationTool.generate (GenerationTool.java:228)
    at org.jooq.codegen.maven.Plugin.execute (Plugin.java:207)
    at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo (DefaultBuildPluginManager.java:137)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:210)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:156)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:148)
    at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject (LifecycleModuleBuilder.java:117)
    at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject (LifecycleModuleBuilder.java:81)
    at org.apache.maven.lifecycle.internal.builder.singlethreaded.SingleThreadedBuilder.build (SingleThreadedBuilder.java:56)
    at org.apache.maven.lifecycle.internal.LifecycleStarter.execute (LifecycleStarter.java:128)
    at org.apache.maven.DefaultMaven.doExecute (DefaultMaven.java:305)
    at org.apache.maven.DefaultMaven.doExecute (DefaultMaven.java:192)
    at org.apache.maven.DefaultMaven.execute (DefaultMaven.java:105)
    at org.apache.maven.cli.MavenCli.execute (MavenCli.java:957)
    at org.apache.maven.cli.MavenCli.doMain (MavenCli.java:289)
    at org.apache.maven.cli.MavenCli.main (MavenCli.java:193)
    at sun.reflect.NativeMethodAccessorImpl.invoke0 (Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke (NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke (DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke (Method.java:498)
    at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced (Launcher.java:282)
    at org.codehaus.plexus.classworlds.launcher.Launcher.launch (Launcher.java:225)
    at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode (Launcher.java:406)
    at org.codehaus.plexus.classworlds.launcher.Launcher.main (Launcher.java:347)
Caused by: java.lang.ArrayIndexOutOfBoundsException: Array index out of range: 1
    at org.hibernate.mapping.Column.getSqlTypeCode (Column.java:200)
    at org.hibernate.mapping.Column.getSqlType (Column.java:238)
    at org.hibernate.tool.schema.internal.StandardTableExporter.getSqlCreateStrings (StandardTableExporter.java:96)
    at org.hibernate.tool.schema.internal.StandardTableExporter.getSqlCreateStrings (StandardTableExporter.java:30)
    at org.hibernate.tool.schema.internal.SchemaCreatorImpl.createFromMetadata (SchemaCreatorImpl.java:315)
    at org.hibernate.tool.schema.internal.SchemaCreatorImpl.performCreation (SchemaCreatorImpl.java:166)
    at org.hibernate.tool.schema.internal.SchemaCreatorImpl.doCreation (SchemaCreatorImpl.java:135)
    at org.hibernate.tool.schema.internal.SchemaCreatorImpl.doCreation (SchemaCreatorImpl.java:121)
    at org.hibernate.tool.hbm2ddl.SchemaExport.doExecution (SchemaExport.java:296)
    at org.hibernate.tool.hbm2ddl.SchemaExport.execute (SchemaExport.java:249)
    at org.hibernate.tool.hbm2ddl.SchemaExport.execute (SchemaExport.java:228)
    at org.hibernate.tool.hbm2ddl.SchemaExport.create (SchemaExport.java:220)
    at org.jooq.meta.extensions.jpa.JPADatabase.export (JPADatabase.java:156)
    at org.jooq.meta.extensions.AbstractInterpretingDatabase.connection (AbstractInterpretingDatabase.java:100)
    at org.jooq.meta.extensions.AbstractInterpretingDatabase.create0 (AbstractInterpretingDatabase.java:77)
    at org.jooq.meta.AbstractDatabase.create (AbstractDatabase.java:296)
    at org.jooq.meta.AbstractDatabase.create (AbstractDatabase.java:285)
    at org.jooq.meta.AbstractDatabase.setConnection (AbstractDatabase.java:275)
    at org.jooq.codegen.GenerationTool.run0 (GenerationTool.java:532)
    at org.jooq.codegen.GenerationTool.run (GenerationTool.java:233)
    at org.jooq.codegen.GenerationTool.generate (GenerationTool.java:228)
    at org.jooq.codegen.maven.Plugin.execute (Plugin.java:207)
    at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo (DefaultBuildPluginManager.java:137)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:210)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:156)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:148)
    at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject (LifecycleModuleBuilder.java:117)


对于简单的自定义类型,如果我使用 JPA 属性转换器,那么它就可以正常工作。我知道不直接支持通过 JPA 属性转换器将多列匹配到单个属性(如果我没记错的话)

谁能指导我如何使用 JPADatabase 处理 JOOQ 代码生成的复合类型?谢谢。

更新:

关于代码生成的问题与投影结构有关,并且 类 在类路径中缺失。但是,关于复合类型的处理,请参阅已接受的答案。

关于错误

我假设您缺少对代码生成 class 路径的依赖。一旦你更新了你的问题,我就会更新我的答案。

关于 @TypeDef 等的 jOOQ 代码生成支持

jOOQ 不会在开箱即用的生成代码中支持您生成的复合类型,您仍然必须为此添加强制类型配置,可能是可嵌入类型配置:

请注意,JPADatabase 通过非常快速地与简单的 JPA 定义模式集成,提供了一个快速的胜利。它有它的警告。为了获得最佳结果,我建议首先使用 DDL(并从中生成 jOOQ 代码和 JPA 模型),因为将模式更改管理置于版本控制之下会容易得多,例如通过 Flyway 或 Liquibase。