如何生成Swagger代码生成器Java模型作为JPA实体

11

我正在使用Swagger Codegen创建Java模型,用于Spring REST服务器,想知道如何让Swagger将每个模型声明为JPA实体。

我使用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>

目前它的样子是这样的,这是生成的缩写 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;

  ...
}

如何让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;

  ...
}

这样,我只需要将以下内容添加到我的pom.xml中,Spring就可以自动将这些生成的类作为REST API暴露出来:

这样,我只需将以下内容添加到我的pom.xml中,Spring便可自动将这些生成的类作为 REST API 暴露出来:

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

然后我可以使用Spring-Data创建JPA存储库,如下所示:

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

今天早上我正在寻找这个,我不相信它已经完成了,因为将整个模型暴露在前端被认为是一种安全风险。坚持使用DTO层会迫使您考虑哪些部分的模型供用户使用,例如名称、出生日期等,而不是内部系统的角色和其他内容。尽管如此...我无法相信这还没有完成,并且Swagger合同中包含某种形式的暴露机制,只需说,不要将此字段暴露给前端? - Mark Gargan
我最终不得不修改Swagger代码生成器的代码。结果证明比最初想象的要复杂,因为您必须定义至少OneToMany、Embedded和Embedable注释,这并不是一件微不足道的事情,如果不以通用方式进行,则几乎不可能完成。我已经创建了一个具有特定模型类名称的分支。 - Brady
3个回答

10

最近已经合并了一个PR,修复了你的问题:https://github.com/OpenAPITools/openapi-generator/pull/11775

您需要升级Maven插件以使用最新版本(目前未发布,仅有快照可用)

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

配置可能略有不同。

接下来,您需要在规范中添加 x-class-extra-annotation 和 x-field-extra-annotation。

例如,对于宠物诊所:

  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

@[Mathieu D] 非常好,正是我在寻找的,不过我看到版本6仍处于测试版阶段,即使您在2018年3月发布了这个评论?需要一个发布的版本6 :/ - user2441441
1
https://github.com/OpenAPITools/openapi-generator/releases/tag/v6.0.0等待的人将获得好事 :) - Mathieu D

4
虽然解决这个问题的正确方式肯定是扩展swagger-codegen(可能需要引入某种包含/排除配置),但我通过对生成的文件进行简单的后处理来解决了这个问题。
与OP相反,我使用Gradle而不是Maven,并利用其扩展的过滤功能。对于Maven,可能需要通过Groovy-Maven-Plugin运行Groovy脚本,因为Maven仅支持占位符替换(与Ant一样,因此使用AntRun-Plugin也无法工作)。
我使用了一个简单的启发式规则,仅包括具有ID的实体 - 逻辑如下:
- 对于所有包含ID字段的Java文件
1. 在包声明后包含javax.persistence.*的导入语句 2. 在类定义之前添加@Entity注解 3. 对于ID字段,添加注释@Id和@GeneratedValue 4. (基于字段名称、其他注释 - 如@OneToMany等 - 也可以添加)
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 }        }
    }
}

2
所以我其实在问自己同样的问题。我找到了一个例子,但那个人只是重新定义了他的POJO,并提供了一种将生成的POJO适应手写POJO的方法。这很繁琐而且不具有发展性。
总体来说,这可能很困难,因为我不确定在您的swagger中是否有一种方式来决定哪些POJO将启用JPA,也许您不希望它们全部出现在您的数据库中(?) 另外,在swagger中如何标记ID呢? 如果您知道这样的方法,您可以始终修改mustache(我想是pojo.mustache)以给您缺少的注释。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接