首页 > 解决方案 > Spring Boot 2:使用 hibernate-jpamodelgen 时出现重复注释问题

问题描述

我有一个简单的 Spring Boot 2 应用程序,使用hibernate-jpamodelgen. 这是整个 Maven POM:

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
      <modelVersion>4.0.0</modelVersion>

      <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.2.RELEASE</version>
      </parent>

      <groupId>gov.idaho.isp</groupId>
      <artifactId>SpringBootJpaModelGenIssue</artifactId>
      <version>0.1</version>  
      <packaging>jar</packaging>

      <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <tomcat.version>9.0.5</tomcat.version>
        <java.version>1.8</java.version>
      </properties>

      <dependencies>
        <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-devtools</artifactId>
          <optional>true</optional>
        </dependency>

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

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

        <dependency>
          <groupId>com.h2database</groupId>
          <artifactId>h2</artifactId>
        </dependency>

        <dependency>
          <groupId>org.hibernate</groupId>
          <artifactId>hibernate-jpamodelgen</artifactId>
        </dependency>
      </dependencies>

    </project>

该应用程序包含一个简单的实体,具有@NotNullJava bean 验证约束注释的 Widget:

    import java.io.Serializable;
    import javax.persistence.Entity;
    import javax.persistence.GeneratedValue;
    import javax.persistence.Id;
    import javax.validation.constraints.NotNull;

    @Entity
    public class Widget implements Serializable {
      @Id @GeneratedValue
      private Long id;

      @NotNull
      private String name;
      ...
    }

运行此 Spring Boot 应用程序然后对此实体进行更改时,由于错误,应用程序无法成功重新启动:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: Invocation of init method failed; nested exception is javax.persistence.PersistenceException: [PersistenceUnit: default] Unable to build Hibernate SessionFactory; nested exception is org.hibernate.cfg.beanvalidation.IntegrationException: Error activating Bean Validation integration

最终根本原因是:

Caused by: java.lang.annotation.AnnotationFormatError: Duplicate annotation for class: interface javax.validation.constraints.NotNull: @javax.validation.constraints.NotNull(message={javax.validation.constraints.NotNull.message}, groups=[], payload=[])

hibernate-jpamodelgen如果删除了依赖项,此重新启动错误就会消失。这是一个已知的问题?

请参阅https://github.com/BriceRoncace/SpringBootJpaModelGenIssue上的示例应用程序以重新创建问题。(我在 Spring Boot 2.0.0 和 2.0.2 中遇到过这个问题。)

标签: spring-bootspring-data-jpabean-validation

解决方案


一种解决方法是使用maven-processor-plugin明确指定org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor应该执行并将hibernate-jpamodelgen依赖项移动到插件定义中:

<plugin>
  <groupId>org.bsc.maven</groupId>
  <artifactId>maven-processor-plugin</artifactId>
  <version>3.3.3</version>
  <executions>
    <execution>
      <id>process</id>
      <goals>
        <goal>process</goal>
      </goals>
      <phase>generate-sources</phase>
      <configuration>
        <processors>                                
          <processor>org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor</processor>
        </processors>
      </configuration>
    </execution>
  </executions>
  <dependencies>
    <dependency>
      <groupId>org.hibernate</groupId>
      <artifactId>hibernate-jpamodelgen</artifactId>
      <version>5.2.17.Final</version>
    </dependency>
  </dependencies>
</plugin>

hibernate 元模型文档表明您应该禁用编译器插件的注释处理:

<plugin>
  <artifactId>maven-compiler-plugin</artifactId>
  <configuration>
    <compilerArgument>-proc:none</compilerArgument>
  </configuration>
</plugin>

但是,我发现即使不禁用编译器注解处理,上面报的spring boot重启错误也消失了。

请参阅提交https://github.com/BriceRoncace/SpringBootJpaModelGenIssue/commit/033ba0078b519d188e7d4c0e6ec66f4278d50ab1


推荐阅读