【问题标题】:How to generate the JPA entity Metamodel?如何生成 JPA 实体元模型?
【发布时间】:2011-03-03 12:42:12
【问题描述】:

本着与CriteriaQuery 相关的类型安全精神,JPA 2.0 还具有支持Metamodel 实体表示的 API。

是否有人知道此 API 的完整功能实现(生成元模型而不是手动创建元模型类)?如果有人也知道在 Eclipse 中设置它的步骤,那就太棒了(我认为它就像设置注释处理器一样简单,但你永远不知道)。

编辑: 刚刚偶然发现Hibernate JPA 2 Metamodel Generator 。但问题仍然存在,因为我找不到该 jar 的任何下载链接。

编辑 2: 自从我问这个问题以来已经过去了一段时间,但我想我会回来并添加指向Hibernate JPA Model Generator project on SourceForge的链接

【问题讨论】:

    标签: java hibernate jpa annotation-processing metamodel


    【解决方案1】:

    如果有人也知道在 Eclipse 中设置它的步骤,那就太棒了(我假设它就像设置注释处理器一样简单,但你永远不知道)

    是的。以下是各种 JPA 2.0 实现的实现和说明:

    EclipseLink

    休眠

    OpenJPA

    数据核


    最新的 Hibernate 实现位于:

    较旧的 Hibernate 实现位于:

    【讨论】:

    • DataNucleus 链接已失效。
    • Hibernate 链接也失效了
    【解决方案2】:

    请看jpa-metamodels-with-maven-example

    休眠

    • 我们需要org.hibernate.org:hibernate-jpamodelgen
    • 处理器类是org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor

    休眠作为依赖项

        <dependency>
          <groupId>org.hibernate.orm</groupId>
          <artifactId>hibernate-jpamodelgen</artifactId>
          <version>${version.hibernate-jpamodelgen}</version>
          <scope>provided</scope>
        </dependency>
    

    作为处理器休眠

          <plugin>
            <groupId>org.bsc.maven</groupId>
            <artifactId>maven-processor-plugin</artifactId>
            <executions>
              <execution>
                <goals>
                  <goal>process</goal>
                </goals>
                <phase>generate-sources</phase>
                <configuration>
                  <compilerArguments>-AaddGeneratedAnnotation=false</compilerArguments> <!-- suppress java.annotation -->
                  <processors>
                    <processor>org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor</processor>
                  </processors>
                </configuration>
              </execution>
            </executions>
            <dependencies>
              <dependency>
                <groupId>org.hibernate.orm</groupId>
                <artifactId>hibernate-jpamodelgen</artifactId>
                <version>${version.hibernate-jpamodelgen}</version>
              </dependency>
            </dependencies>
          </plugin>
    

    OpenJPA

    • 我们需要org.apache.openjpa:openjpa
    • 处理器类是org.apache.openjpa.persistence.meta.AnnotationProcessor6
    • OpenJPA 似乎需要额外的元素 &lt;openjpa.metamodel&gt;true&lt;openjpa.metamodel&gt;

    OpenJPA 作为依赖项

      <dependencies>
        <dependency>
          <groupId>org.apache.openjpa</groupId>
          <artifactId>openjpa</artifactId>
          <scope>provided</scope>
        </dependency>
      </dependencies>
      <build>
        <plugins>
          <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <configuration>
              <compilerArgs>
                <arg>-Aopenjpa.metamodel=true</arg>
              </compilerArgs>
            </configuration>
          </plugin>
        </plugins>
      </build>
    

    OpenJPA 作为处理器

          <plugin>
            <groupId>org.bsc.maven</groupId>
            <artifactId>maven-processor-plugin</artifactId>
            <executions>
              <execution>
                <id>process</id>
                <goals>
                  <goal>process</goal>
                </goals>
                <phase>generate-sources</phase>
                <configuration>
                  <processors>
                    <processor>org.apache.openjpa.persistence.meta.AnnotationProcessor6</processor>
                  </processors>
                  <optionMap>
                    <openjpa.metamodel>true</openjpa.metamodel>
                  </optionMap>
                </configuration>
              </execution>
            </executions>
            <dependencies>
              <dependency>
                <groupId>org.apache.openjpa</groupId>
                <artifactId>openjpa</artifactId>
                <version>${version.openjpa}</version>
              </dependency>
            </dependencies>
          </plugin>
    

    EclipseLink

    • 我们需要org.eclipse.persistence:org.eclipse.persistence.jpa.modelgen.processor
    • 处理器类是org.eclipse.persistence.internal.jpa.modelgen.CanonicalModelProcessor
    • EclipseLink 需要persistence.xml

    EclipseLink 作为依赖项

      <dependencies>
        <dependency>
          <groupId>org.eclipse.persistence</groupId>
          <artifactId>org.eclipse.persistence.jpa.modelgen.processor</artifactId>
          <scope>provided</scope>
        </dependency>
    

    EclipseLink 作为处理器

        <plugins>
          <plugin>
            <groupId>org.bsc.maven</groupId>
            <artifactId>maven-processor-plugin</artifactId>
            <executions>
              <execution>
                <goals>
                  <goal>process</goal>
                </goals>
                <phase>generate-sources</phase>
                <configuration>
                  <processors>
                    <processor>org.eclipse.persistence.internal.jpa.modelgen.CanonicalModelProcessor</processor>
                  </processors>
                  <compilerArguments>-Aeclipselink.persistencexml=src/main/resources-${environment.id}/META-INF/persistence.xml</compilerArguments>
                </configuration>
              </execution>
            </executions>
            <dependencies>
              <dependency>
                <groupId>org.eclipse.persistence</groupId>
                <artifactId>org.eclipse.persistence.jpa.modelgen.processor</artifactId>
                <version>${version.eclipselink}</version>
              </dependency>
            </dependencies>
          </plugin>
    

    数据核

    • 我们需要org.datanucleus:datanucleus-jpa-query
    • 处理器类是org.datanucleus.jpa.query.JPACriteriaProcessor

    DataNucleus 作为依赖项

      <dependencies>
        <dependency>
          <groupId>org.datanucleus</groupId>
          <artifactId>datanucleus-jpa-query</artifactId>
          <scope>provided</scope>
        </dependency>
      </dependencies>
    

    DataNucleus 作为处理器

          <plugin>
            <groupId>org.bsc.maven</groupId>
            <artifactId>maven-processor-plugin</artifactId>
            <executions>
              <execution>
                <id>process</id>
                <goals>
                  <goal>process</goal>
                </goals>
                <phase>generate-sources</phase>
                <configuration>
                  <processors>
                    <processor>org.datanucleus.jpa.query.JPACriteriaProcessor</processor>
                  </processors>
                </configuration>
              </execution>
            </executions>
            <dependencies>
              <dependency>
                <groupId>org.datanucleus</groupId>
                <artifactId>datanucleus-jpa-query</artifactId>
                <version>${version.datanucleus}</version>
              </dependency>
            </dependencies>
          </plugin>
    

    【讨论】:

    • 为了清楚一点,生成的东西可以与eclipselink一起使用,即使你使用hibernate来生成它,我也无法从netbeans 8生成元模型,不得不创建一个maven测试项目来生成我的东西
    • @ymajoros 是否禁止在 SO 中说 something is recommended 而没有 IMHO?我不代表任何人。
    • 顺便说一句,请参阅 Sorter 对 EclipseLink 的回答。这是我多年来一直使用的配置,它运行良好。 stackoverflow.com/questions/3037593/…
    • 这个实现不是特定的吗?我尝试使用 Hibernate 生成的元模型和 EclipseLink 并获得 NullPointerException
    • 也许值得一提的是,对于带有 Java11 的 hibernate-jpamodelgen,maven-processor-plugin 至少应该是 4.0-rc 版本。见stackoverflow.com/a/61305429/5911964
    【解决方案3】:

    Eclipse 通过 Dali 提供的 JPA 2.0 支持(包含在“面向 JEE 开发人员的 Eclipse IDE”中)拥有自己的与 Eclipse 集成的元模型生成器。

    1. 包资源管理器中选择您的项目
    2. 转到 属性 -> JPA 对话框
    3. Canonical metamodel (JPA 2.0) 组中选择源文件夹
    4. 点击应用按钮在选定的源文件夹中生成元模型类

    这应该适用于任何 JPA 提供程序,因为生成的类是标准的。

    另见here

    【讨论】:

    • 有什么方法可以自己启动这个过程吗?这不能可靠地为我生成元模型
    【解决方案4】:

    假设我们的应用程序使用以下PostPostCommentPostDetailsTag 实体,它们形成了一对多、一对一和多对多的表关系:

    如何生成 JPA 标准元模型

    Hibernate ORM 提供的hibernate-jpamodelgen 工具可用于扫描项目实体并生成JPA Criteria Metamodel。只需在 Maven pom.xml 配置文件中的maven-compiler-plugin 中添加以下annotationProcessorPath

    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>${maven-compiler-plugin.version}</version>
        <configuration>
            <annotationProcessorPaths>
                <annotationProcessorPath>
                    <groupId>org.hibernate</groupId>
                    <artifactId>hibernate-jpamodelgen</artifactId>
                    <version>${hibernate.version}</version>
                </annotationProcessorPath>
            </annotationProcessorPaths>
        </configuration>
    </plugin>
    

    现在,当项目编译完成后,可以看到在target文件夹中,生成了以下Java类:

    > tree target/generated-sources/
    target/generated-sources/
    └── annotations
        └── com
            └── vladmihalcea
                └── book
                    └── hpjp
                        └── hibernate
                            ├── forum
                            │   ├── PostComment_.java
                            │   ├── PostDetails_.java
                            │   ├── Post_.java
                            │   └── Tag_.java
    

    标记实体元模型

    如果Tag实体映射如下:

    @Entity
    @Table(name = "tag")
    public class Tag {
    
        @Id
        private Long id;
    
        private String name;
    
        //Getters and setters omitted for brevity
    }
    

    Tag_ 元模型类是这样生成的:

    @Generated(value = "org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor")
    @StaticMetamodel(Tag.class)
    public abstract class Tag_ {
    
        public static volatile SingularAttribute<Tag, String> name;
        public static volatile SingularAttribute<Tag, Long> id;
    
        public static final String NAME = "name";
        public static final String ID = "id";
    }
    

    SingularAttribute 用于基本的idname Tag JPA 实体属性。

    发布实体元模型

    Post 实体的映射如下:

    @Entity
    @Table(name = "post")
    public class Post {
    
        @Id
        private Long id;
    
        private String title;
    
        @OneToMany(
            mappedBy = "post",
            cascade = CascadeType.ALL,
            orphanRemoval = true
        )
        private List<PostComment> comments = new ArrayList<>();
    
        @OneToOne(
            mappedBy = "post",
            cascade = CascadeType.ALL,
            fetch = FetchType.LAZY
        )
        @LazyToOne(LazyToOneOption.NO_PROXY)
        private PostDetails details;
    
        @ManyToMany
        @JoinTable(
            name = "post_tag",
            joinColumns = @JoinColumn(name = "post_id"),
            inverseJoinColumns = @JoinColumn(name = "tag_id")
        )
        private List<Tag> tags = new ArrayList<>();
        
        //Getters and setters omitted for brevity
    }
    

    Post 实体有两个基本属性,idtitle、一对多 comments 集合、一对一 details 关联和多对多tags收藏。

    Post_ Metamodel 类生成如下:

    @Generated(value = "org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor")
    @StaticMetamodel(Post.class)
    public abstract class Post_ {
    
        public static volatile ListAttribute<Post, PostComment> comments;
        public static volatile SingularAttribute<Post, PostDetails> details;
        public static volatile SingularAttribute<Post, Long> id;
        public static volatile SingularAttribute<Post, String> title;
        public static volatile ListAttribute<Post, Tag> tags;
    
        public static final String COMMENTS = "comments";
        public static final String DETAILS = "details";
        public static final String ID = "id";
        public static final String TITLE = "title";
        public static final String TAGS = "tags";
    }
    

    基本的idtitle 属性以及一对一的details 关联由SingularAttribute 表示,而commentstags 集合由JPA 表示ListAttribute.

    PostDetails 实体元模型

    PostDetails 实体的映射如下:

    @Entity
    @Table(name = "post_details")
    public class PostDetails {
    
        @Id
        @GeneratedValue
        private Long id;
    
        @Column(name = "created_on")
        private Date createdOn;
    
        @Column(name = "created_by")
        private String createdBy;
    
        @OneToOne(fetch = FetchType.LAZY)
        @MapsId
        @JoinColumn(name = "id")
        private Post post;
        
        //Getters and setters omitted for brevity
    }
    

    所有实体属性都将由关联的PostDetails_ 元模型类中的 JPA SingularAttribute 表示:

    @Generated(value = "org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor")
    @StaticMetamodel(PostDetails.class)
    public abstract class PostDetails_ {
    
        public static volatile SingularAttribute<PostDetails, Post> post;
        public static volatile SingularAttribute<PostDetails, String> createdBy;
        public static volatile SingularAttribute<PostDetails, Long> id;
        public static volatile SingularAttribute<PostDetails, Date> createdOn;
    
        public static final String POST = "post";
        public static final String CREATED_BY = "createdBy";
        public static final String ID = "id";
        public static final String CREATED_ON = "createdOn";
    }
    

    PostComment 实体元模型

    PostComment 映射如下:

    @Entity
    @Table(name = "post_comment")
    public class PostComment {
    
        @Id
        private Long id;
    
        @ManyToOne(fetch = FetchType.LAZY)
        private Post post;
    
        private String review;
        
        //Getters and setters omitted for brevity
    }
    

    并且,所有实体属性都由关联的 PostComments_ 元模型类中的 JPA SingularAttribute 表示:

    @Generated(value = "org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor")
    @StaticMetamodel(PostComment.class)
    public abstract class PostComment_ {
    
        public static volatile SingularAttribute<PostComment, Post> post;
        public static volatile SingularAttribute<PostComment, String> review;
        public static volatile SingularAttribute<PostComment, Long> id;
    
        public static final String POST = "post";
        public static final String REVIEW = "review";
        public static final String ID = "id";
    }
    

    使用 JPA 标准元模型

    如果没有 JPA 元模型,需要获取由关联的 Post 标题过滤的 PostComment 实体的 Criteria API 查询将如下所示:

    CriteriaBuilder builder = entityManager.getCriteriaBuilder();
    
    CriteriaQuery<PostComment> query = builder.createQuery(PostComment.class);
    Root<PostComment> postComment = query.from(PostComment.class);
    
    Join<PostComment, Post> post = postComment.join("post");
    
    query.where(
        builder.equal(
            post.get("title"),
            "High-Performance Java Persistence"
        )
    );
    
    List<PostComment> comments = entityManager
        .createQuery(query)
        .getResultList();
    

    请注意,我们在创建 Join 实例时使用了 post 字符串文字,而在引用 Post title 时我们使用了 title 字符串文字。

    JPA 元模型允许我们避免硬编码实体属性,如下例所示:

    CriteriaBuilder builder = entityManager.getCriteriaBuilder();
    
    CriteriaQuery<PostComment> query = builder.createQuery(PostComment.class);
    Root<PostComment> postComment = query.from(PostComment.class);
    
    Join<PostComment, Post> post = postComment.join(PostComment_.post);
    
    query.where(
        builder.equal(
            post.get(Post_.title),
            "High-Performance Java Persistence"
        )
    );
    
    List<PostComment> comments = entityManager
        .createQuery(query)
        .getResultList();
    

    或者,假设我们要在过滤 Post titlePostDetails createdOn 属性时获取 DTO 投影。

    我们可以在创建连接属性时使用元模型,以及在构建 DTO 投影列别名或引用我们需要过滤的实体属性时:

    CriteriaBuilder builder = entityManager.getCriteriaBuilder();
    
    CriteriaQuery<Object[]> query = builder.createQuery(Object[].class);
    
    Root<PostComment> postComment = query.from(PostComment.class);
    Join<PostComment, Post> post = postComment.join(PostComment_.post);
    
    query.multiselect(
        postComment.get(PostComment_.id).alias(PostComment_.ID),
        postComment.get(PostComment_.review).alias(PostComment_.REVIEW),
        post.get(Post_.title).alias(Post_.TITLE)
    );
    
    query.where(
        builder.and(
            builder.like(
                post.get(Post_.title),
                "%Java Persistence%"
            ),
            builder.equal(
                post.get(Post_.details).get(PostDetails_.CREATED_BY),
                "Vlad Mihalcea"
            )
        )
    );
    
    List<PostCommentSummary> comments = entityManager
        .createQuery(query)
        .unwrap(Query.class)
        .setResultTransformer(Transformers.aliasToBean(PostCommentSummary.class))
        .getResultList();
    

    很酷,对吧?

    【讨论】:

      【解决方案5】:

      对于eclipselink,只需要以下依赖即可生成元模型。不需要其他任何东西。

          <dependency>
              <groupId>org.eclipse.persistence</groupId>
              <artifactId>org.eclipse.persistence.jpa.modelgen.processor</artifactId>
              <version>2.5.1</version>
              <scope>provided</scope>
          </dependency>
      

      【讨论】:

      【解决方案6】:

      对于 Hibernate 作为提供者,这是最常见的恕我直言:

      如果使用 Gradle、Maven 等构建工具,您需要在类路径和编译器级别中包含 Hibernate JPA 2 Metamodel Generator jar>=1.6,这就是您构建项目所需的全部内容,并且元模型将自动生成。

      在 IDE Eclipse 的情况下 1.转到项目->属性->Java编译器->注释处理并启用它。 2.展开Annotation Processing->Factory Path->Add External Jar add Hibernate JPA 2 Metamodel Generator jar 检查新添加的jar并说OK。清理并构建完成!

      来自 maven repo 的链接 Hibernate JPA 2 Metamodel Generator jar 链接 https://mvnrepository.com/artifact/org.hibernate/hibernate-jpamodelgen

      【讨论】:

      • 在我的情况下,将&lt;dependencies&gt; &lt;dependency&gt; &lt;groupId&gt;org.hibernate&lt;/groupId&gt; &lt;artifactId&gt;hibernate-jpamodelgen&lt;/artifactId&gt; &lt;scope&gt;compile&lt;/scope&gt; &lt;/dependency&gt; &lt;/dependencies&gt; 添加到 pom.xml 就足够了。
      • 在使用 maven 和 Eclipse 时是否需要这两种配置?
      • 即使在 pom 中添加了 hibernate-jpamodelgen,我也必须这样做并且它有效
      • 这也应该是公认的答案。非常感谢桑迪普
      【解决方案7】:

      好的,根据我在这里阅读的内容,我是通过这种方式使用 EclipseLink 完成的,我不需要将处理器依赖项放入项目中,只需作为 annotationProcessorPath 的元素编译器插件。

          <plugin>
              <artifactId>maven-compiler-plugin</artifactId>
              <configuration>
                  <annotationProcessorPaths>
                      <annotationProcessorPath>
                          <groupId>org.eclipse.persistence</groupId>
                          <artifactId>org.eclipse.persistence.jpa.modelgen.processor</artifactId>
                          <version>2.7.7</version>
                      </annotationProcessorPath>
                  </annotationProcessorPaths>
                  <compilerArgs>
                      <arg>-Aeclipselink.persistencexml=src/main/resources/META-INF/persistence.xml</arg>
                  </compilerArgs>
              </configuration>
          </plugin>
      

      【讨论】:

        猜你喜欢
        • 2014-02-22
        • 2011-10-14
        • 2012-03-25
        • 2018-12-25
        • 2017-11-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多