Java 如何生成JPA实体元模型?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3037593/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 15:53:09  来源:igfitidea点击:

How to generate the JPA entity Metamodel?

javahibernatejpaannotation-processingmetamodel

提问by Andrey

In the spirit of type safety associated with the CriteriaQueryJPA 2.0 also has an API to support Metamodelrepresentation of entities.

本着与CriteriaQuery相关的类型安全的精神,JPA 2.0 也有一个 API 来支持实体的元模型表示。

Is anyone aware of a fully functional implementation of this API (to generate the Metamodel as opposed to creating the metamodel classes manually)? It would be awesome if someone also knows the steps for setting this up in Eclipse (I assume it's as simple as setting up an annotation processor, but you never know).

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

EDIT: Just stumbled across Hibernate JPA 2 Metamodel Generator . But the issue remains since I can't find any download links for the jar.

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

EDIT 2: Awhile has passed since I asked this question, but I thought I'd come back and add a link to the Hibernate JPA Model Generator project on SourceForge

编辑 2:自从我问这个问题以来已经过去了一段时间,但我想我会回来并在 SourceForge 上添加一个指向Hibernate JPA 模型生成器项目的链接

采纳答案by Pascal Thivent

It would be awesome if someone also knows the steps for setting this up in Eclipse (I assume it's as simple as setting up an annotation processor, but you never know)

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

Yes it is. Here are the implementations and instructions for the various JPA 2.0 implementations:

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

EclipseLink

Eclipse链接

Hibernate

休眠

OpenJPA

开放式JPA

DataNucleus

数据核



The latest Hibernate implementation is available at:

最新的 Hibernate 实现可在以下位置获得:

An older Hibernate implementation is at:

较旧的 Hibernate 实现位于:

回答by Jin Kwon

Please take a look at jpa-metamodels-with-maven-example.

请看一下jpa-metamodels-with-maven-example

Hibernate

休眠

  • We need org.hibernate.org:hibernate-jpamodelgen.
  • The processor class is org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor.
  • 我们需要org.hibernate.org:hibernate-jpamodelgen.
  • 处理器类是org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor.

Hibernate as a dependency

Hibernate 作为依赖

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

Hibernate as a processor

作为处理器休眠

      <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

开放式JPA

  • We need org.apache.openjpa:openjpa.
  • The processor class is org.apache.openjpa.persistence.meta.AnnotationProcessor6.
  • OpenJPA seems require additional element <openjpa.metamodel>true<openjpa.metamodel>.
  • 我们需要org.apache.openjpa:openjpa.
  • 处理器类是org.apache.openjpa.persistence.meta.AnnotationProcessor6.
  • OpenJPA 似乎需要额外的元素<openjpa.metamodel>true<openjpa.metamodel>

OpenJPA as a dependency

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 as a processor

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

Eclipse链接

  • We need org.eclipse.persistence:org.eclipse.persistence.jpa.modelgen.processor.
  • The processor class is org.eclipse.persistence.internal.jpa.modelgen.CanonicalModelProcessor.
  • EclipseLink requires persistence.xml.
  • 我们需要org.eclipse.persistence:org.eclipse.persistence.jpa.modelgen.processor.
  • 处理器类是org.eclipse.persistence.internal.jpa.modelgen.CanonicalModelProcessor.
  • EclipseLink 需要persistence.xml.

EclipseLink as a dependency

EclipseLink 作为依赖项

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

EclipseLink as a processor

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>

DataNucleus

数据核

  • We need org.datanucleus:datanucleus-jpa-query.
  • The processor class is org.datanucleus.jpa.query.JPACriteriaProcessor.
  • 我们需要org.datanucleus:datanucleus-jpa-query.
  • 处理器类是org.datanucleus.jpa.query.JPACriteriaProcessor.

DataNucleus as a dependency

DataNucleus 作为依赖项

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

DataNucleus as a processor

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>

回答by James

Eclipse's JPA 2.0 support through Dali (which is included in "Eclipse IDE for JEE Developers") has its own metamodel generator integrated with Eclipse.

Eclipse 通过 Dali 提供的 JPA 2.0 支持(包含在“Eclipse IDE for JEE Developers”中)具有与 Eclipse 集成的自己的元模型生成器。

  1. Select your project in the Package Explorer
  2. Go to Properties-> JPAdialog
  3. Select source folder from Canonical metamodel (JPA 2.0)group
  4. Click Applybutton to generate metamodel classes in the selected source folder
  1. Package Explorer 中选择您的项目
  2. 转到“属性”->“ JPA”对话框
  3. 规范元模型 (JPA 2.0)组中选择源文件夹
  4. 单击应用按钮在选定的源文件夹中生成元模型类

enter image description here

在此处输入图片说明

This should work on any JPA provider as the generated classes are standard.

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

Also see here.

另请参阅此处

回答by Sorter

For eclipselink, only the following dependency is sufficient to generate metamodel. Nothing else is needed.

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

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

回答by SandeepGodara

For Hibernate as provider which is most common IMHO:

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

In case of build tools like Gradle, Maven you need to have Hibernate JPA 2 Metamodel Generator jar in the classpath and compiler level>=1.6 that is all you need build the project and metamodel will be generated automatically.

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

In case of IDE Eclipse 1. goto Project->Properties->Java Compiler->Annotation Processing and enable it. 2. Expand Annotation Processing->Factory Path-> Add External Jar add Hibernate JPA 2 Metamodel Generator jar check the newly added jar and say OK. Clean and Build done!

如果是 IDE Eclipse 1. 转到 Project->Properties->Java Compiler->Annotation Processing 并启用它。2. 展开Annotation Processing->Factory Path-> Add External Jar add Hibernate JPA 2 Metamodel Generator jar 勾选新添加的jar并说OK。清洁和构建完成!

Link Hibernate JPA 2 Metamodel Generator jar link from maven repo https://mvnrepository.com/artifact/org.hibernate/hibernate-jpamodelgen

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

回答by Vlad Mihalcea

Since this is a very common question, I wrote this article, on which this answer is based on.

由于这是一个非常常见的问题,我写了这篇文章,这个答案是基于它。

Let's assume our application uses the following Post, PostComment, PostDetails, and Tagentities, which form a one-to-many, one-to-one, and many-to-many table relationships:

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

JPA Criteria Metamodel

JPA 标准元模型

How to generate the JPA Criteria Metamodel

如何生成 JPA 标准元模型

The hibernate-jpamodelgentool provided by Hibernate ORM can be used to scan the project entities and generate the JPA Criteria Metamodel. All you need to do is add the following annotationProcessorPathto the maven-compiler-pluginin the Maven pom.xmlconfiguration file:

hibernate-jpamodelgenHibernate ORM 提供的工具可用于扫描项目实体并生成 JPA Criteria Metamodel。您需要做的就是将以下内容添加annotationProcessorPathmaven-compiler-pluginMavenpom.xml配置文件中:

<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>

Now, when the project is compiled, you can see that in the targetfolder, the following Java classes are generated:

现在,当编译项目时,您可以看到在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 Metamodel

标签实体元模型

If the Tagentity is mapped as follows:

如果Tag实体映射如下:

@Entity
@Table(name = "tag")
public class Tag {

    @Id
    private Long id;

    private String name;

    //Getters and setters omitted for brevity
}

The Tag_Metamodel class is generated like this:

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";
}

The SingularAttributeis used for the basic idand nameTagJPA entity attributes.

SingularAttribute用于基本idnameTagJPA实体的属性。

Post entity Metamodel

发布实体元模型

The Postentity is mapped like this:

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
}

The Postentity has two basic attributes, idand title, a one-to-many commentscollection, a one-to-one detailsassociation, and a many-to-many tagscollection.

Post实体有两个基本属性,id并且title,一到多的comments集合,一个对一个details的关联,和许多一对多的tags集合。

The Post_Metamodel class is generated as follows:

Post_元模型类生成如下:

@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";
}

The basic idand titleattributes, as well as the one-to-one detailsassociation, are represented by a SingularAttributewhile the commentsand tagscollections are represented by the JPA ListAttribute.

基本idtitle属性以及一对一details关联由 a SingularAttributewhilecommentstags集合由 JPA 表示ListAttribute

PostDetails entity Metamodel

PostDetails 实体元模型

The PostDetailsentity is mapped like this:

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
}

All entity attributes are going to be represented by the JPA SingularAttributein the associated PostDetails_Metamodel class:

所有实体属性都将由SingularAttribute关联的PostDetails_Metamodel 类中的 JPA 表示:

@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 entity Metamodel

PostComment 实体元模型

The PostCommentis mapped as follows:

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
}

And, all entity attributes are represented by the JPA SingularAttributein the associated PostComments_Metamodel class:

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

@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";
}

Using the JPA Criteria Metamodel

使用 JPA 标准元模型

Without the JPA Metamodel, a Criteria API query that needs to fetch the PostCommententities filtered by their associated Posttitle would look like this:

如果没有 JPA 元模型,需要获取PostComment由其关联Post标题过滤的实体的 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();

Notice that we used the postString literal when creating the Joininstance, and we used the titleString literal when referencing the Posttitle.

请注意,我们post在创建Join实例时使用了字符串字面量,而title在引用Posttitle.

The JPA Metamodel allows us to avoid hard-coding entity attributes, as illustrated by the following example:

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();

Writing JPA Criteria API queries is much easier if you are using a code completion tool like Codota. Check out this articlefor more details about the Codota IDE plugin.

如果您使用像 Codota 这样的代码完成工具,编写 JPA Criteria API 查询会容易得多。查看这篇文章,了解有关 Codota IDE 插件的更多详细信息。

Or, let's say we want to fetch a DTO projectionwhile filtering the Posttitleand the PostDetailscreatedOnattributes.

或者,假设我们想要在过滤和属性时获取DTO 投影PosttitlePostDetailscreatedOn

We can use the Metamodel when creating the join attributes, as well as when building the DTO projection column aliases or when referencing the entity attributes we need to filter:

我们可以在创建连接属性时使用元模型,以及在构建 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();

Cool, right?

酷,对吧?

回答by dmatej

Ok, based on what I have read here, I did it with EclipseLinkthis way and I did not need to put the processor dependency to the project, only as an annotationProcessorPathelement of the compiler plugin.

好的,根据我在这里读到的内容,我用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>