简体   繁体   English

如何生成 Swagger codegen Java 模型作为 JPA 实体

[英]How to generate Swagger codegen Java models as JPA Entities

I am using Swagger codegen to create Java models to be used in a Spring REST server, and would like to know how to get Swagger to declare each model as a JPA entity.我正在使用 Swagger codegen 创建 Java 模型,用于 Spring REST 服务器,并想知道如何获取 Swagger 以将每个 model 声明为 model 实体.79588249

I generate the code with the swagger-codegen-maven-plugin as follows:我使用swagger-codegen-maven-plugin生成代码如下:

<plugin>
    <groupId>io.swagger</groupId>
    <artifactId>swagger-codegen-maven-plugin</artifactId>
    <version>2.4.0</version>
    <executions>
        <execution>
            <goals>
                <goal>generate</goal>
            </goals>
            <configuration>
                <inputSpec>${project.basedir}/src/main/openApi/Rack.json</inputSpec>
                <language>spring</language>
                <groupId>com.me</groupId>
                <artifactId>rest-server</artifactId>
                <apiPackage>com.me.rest.api</apiPackage>
                <modelPackage>com.me.rest.model</modelPackage>
                <invokerPackage>com.me.rest.invoker</invokerPackage>
                <configOptions>
                    <sourceFolder>src/gen/java/main</sourceFolder>
                    <java8>true</java8>
                    <dateLibrary>java8</dateLibrary>
                </configOptions>
            </configuration>
        </execution>
    </executions>
</plugin>

As I have it now, this is the abbreviated java code that gets generated:正如我现在所拥有的,这是生成的缩写 java 代码:

@Validated
@javax.annotation.Generated(value = "io.swagger.codegen.languages.SpringCodegen", date = "...")

public class Rack   {
  @JsonProperty("id")
  private Long id = null;

  @JsonProperty("name")
  private String name = null;

  ...
}

How do I get Swagger to add the @Entity and @Id JPA annotations, as follows?如何获取 Swagger 添加 @Entity 和 @Id JPA 注释,如下所示?

import javax.persistence.Entity;
import javax.persistence.Id;

@Entity
@Validated
@javax.annotation.Generated(value = "io.swagger.codegen.languages.SpringCodegen", date = "...")

public class Rack   {
  @Id
  @JsonProperty("id")
  private Long id = null;

  @JsonProperty("name")
  private String name = null;

  ...
}

This way, all I would have to do to get Spring to automatically expose these generated classes as REST APIs, would be to add the following to my pom.xml :这样,为了让 Spring 自动将这些生成的类公开为 REST API,我所要做的就是将以下内容添加到我的pom.xml

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-rest</artifactId>
</dependency>

Then I could create the JPA repositories with Spring-Data, as follows:然后我可以用 Spring-Data 创建 JPA 存储库,如下所示:

public interface RackRepository extends CrudRepository<Rack, Long> {
}

A PR has recently been merged fixing your issue: https://github.com/OpenAPITools/openapi-generator/pull/11775最近合并了一个 PR 来解决您的问题: https://github.com/OpenAPITools/openapi-generator/pull/11775

You need to upgrade your Maven plugin to use the latest version (currently unreleased, only snapshot is available)您需要升级您的Maven插件才能使用最新版本(目前未发布,只有快照可用)

<plugin>
    <groupId>org.openapitools</groupId>
    <artifactId>openapi-generator-maven-plugin</artifactId>
    <version>6.0.0-SNAPSHOT</version>
    ...
</plugin>

The configuration might be slightly different.配置可能略有不同。

Then you need to add x-class-extra-annotation and x-field-extra-annotation in your spec.然后你需要在你的规范中添加 x-class-extra-annotation 和 x-field-extra-annotation。

For instance for the Pet Clinic:例如宠物诊所:

  schemas:
    Pet:
      type: object
      x-class-extra-annotation: "@javax.persistence.Entity"
      required:
        - id
        - name
      properties:
        id:
          type: integer
          format: int64
          x-field-extra-annotation: "@javax.persistence.Id"
        name:
          type: string
        tag:
          type: string

While the right way to solve this surely is an extension of swagger-codegen (probably with the introduction of some kind of include/exclude config), I got away with a fairly simply post-processing of the generated files.虽然解决这个问题的正确方法肯定是 swagger-codegen 的扩展(可能是引入了某种包含/排除配置),但我对生成的文件进行了相当简单的后处理。

In contrast to the OP I use Gradle instead of Maven and leveraged its extended filtering functionality.与 OP 相比,我使用Gradle而不是Maven并利用其扩展的过滤功能。 For Maven it is probably necessary to run a Groovy-script by way of the Groovy-Maven-Plugin, since Maven only supports placeholder substitution (as does Ant, so using the AntRun-Plugin would also not work).对于 Maven,可能需要通过 Groovy-Maven-Plugin 运行 Groovy 脚本,因为 Maven 仅支持占位符替换(与 Ant 一样,因此使用 AntRun-Plugin 也不起作用)。

I used a simple heuristic to only include entities with an id - the logic is as follows:我使用了一个简单的启发式方法来只包含带有 id 的实体 - 逻辑如下:

  • for all Java-files containing an ID-field对于包含 ID 字段的所有 Java 文件
    • include import statement for javax.persistence.* after the package declaration在包声明之后包含javax.persistence.*导入语句
    • add the @Entity -annotation before the class definition在类定义之前添加@Entity -annotation
    • for the ID-field, add the annotations @Id and @GeneratedValue对于 ID 字段,添加注释@Id@GeneratedValue
    • (based on field names, other annotations - @OneToMany etc. - may be added as well) (基于字段名称,其他注释 - @OneToMany等 - 也可以添加)

Gradle-users may find the following task useful as a start: Gradle 用户可能会发现以下任务作为开始很有用:

task generateJpaAnnotations(type: Copy) {
    from "${swaggerSources.<modelName>.code.outputDir}/src/main/java"
    into "<output dir>
    include '**/*.java'

    eachFile {
        if (it.file.text.contains("private Long id")) {
            filter { line -> line.contains('package') ? "$line\nimport javax.persistence.*;" : line }
            filter { line -> line.contains('public class') ? "@Entity\n$line" : line }
            filter { line -> line.contains('private Long id') ? "@Id\n@GeneratedValue(strategy=GenerationType.AUTO)\n$line" : line }        }
    }
}

So I'm actually asking myself the same question.所以我实际上也在问自己同样的问题。 I found an example but the guy is simply re-defining his POJOs and providing a way to adapt the generated ones to the handwritten ones.我找到了一个例子,但这个人只是重新定义了他的 POJO 并提供了一种方法来使生成的 POJO 适应手写的 POJO。 Tedious and not evolutive.乏味而不是进化。

Globally this could be hard because I'm not sure there is a way in your swagger to decide which POJO will be JPA enabled and maybe you don't want them all in your DB (?) Also, how to you tag the id in swagger?在全球范围内,这可能很难,因为我不确定您的招摇有没有办法决定哪个 POJO 将启用 JPA,也许您不希望它们都在您的数据库中(?)此外,您如何标记 id昂首阔步? If you know of such a way, you can always modify the mustache (pojo.mustache I guess) to give you the annotations you're missing.如果您知道这种方式,您可以随时修改小胡子(我猜是 pojo.mustache)以提供您缺少的注释。

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

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