简体   繁体   English

如何生成 JPA 实体元模型?

[英]How to generate the JPA entity Metamodel?

In the spirit of type safety associated with the CriteriaQuery JPA 2.0 also has an API to support Metamodel representation 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)?有谁知道这个 API 的全功能实现(生成元模型而不是手动创建元模型类)? 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 中设置它的步骤,那就太棒了(我认为它就像设置注释处理器一样简单,但你永远不知道)。

EDIT: Just stumbled across Hibernate JPA 2 Metamodel Generator .编辑:刚刚偶然发现Hibernate JPA 2 Metamodel Generator But the issue remains since I can't find any download links for the jar.但问题仍然存在,因为我找不到 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 Model Generator 项目的链接

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 实现位于:

Please take a look at jpa-metamodels-with-maven-example .请看一下jpa-metamodels-with-maven-example

Hibernate休眠

  • We need org.hibernate.org:hibernate-jpamodelgen .我们需要org.hibernate.org:hibernate-jpamodelgen
  • The processor class is org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor .处理器类是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 .我们需要org.apache.openjpa:openjpa
  • The processor class is org.apache.openjpa.persistence.meta.AnnotationProcessor6 .处理器类是org.apache.openjpa.persistence.meta.AnnotationProcessor6
  • OpenJPA seems require additional element <openjpa.metamodel>true<openjpa.metamodel> . 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 .我们需要org.eclipse.persistence:org.eclipse.persistence.jpa.modelgen.processor
  • The processor class is org.eclipse.persistence.internal.jpa.modelgen.CanonicalModelProcessor .处理器类是org.eclipse.persistence.internal.jpa.modelgen.CanonicalModelProcessor
  • EclipseLink requires persistence.xml . 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 .我们需要org.datanucleus:datanucleus-jpa-query
  • The processor class is org.datanucleus.jpa.query.JPACriteriaProcessor .处理器类是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>

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

在此处输入图片说明

This should work on any JPA provider as the generated classes are standard.这应该适用于任何 JPA 提供程序,因为生成的类是标准的。

Also see here .另请参阅 此处

Let's assume our application uses the following Post , PostComment , PostDetails , and Tag entities, which form a one-to-many, one-to-one, and many-to-many table relationships:假设我们的应用程序使用以下PostPostCommentPostDetailsTag实体,它们形成一对多、一对一和多对多表关系:

JPA 标准元模型

How to generate the JPA Criteria Metamodel如何生成 JPA 标准元模型

The hibernate-jpamodelgen tool provided by Hibernate ORM can be used to scan the project entities and generate the JPA Criteria Metamodel. Hibernate ORM 提供的hibernate-jpamodelgen工具可用于扫描项目实体并生成 JPA Criteria Metamodel。 All you need to do is add the following annotationProcessorPath to the maven-compiler-plugin in the Maven pom.xml configuration file:您需要做的就是在 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>

Now, when the project is compiled, you can see that in the target folder, 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 Tag entity 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_ Metamodel 类是这样生成的:

@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 SingularAttribute is used for the basic id and name Tag JPA entity attributes. SingularAttribute用于基本的idname Tag JPA 实体属性。

Post entity Metamodel发布实体元模型

The Post entity 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 Post entity has two basic attributes, id and title , a one-to-many comments collection, a one-to-one details association, and a many-to-many tags collection. Post实体有两个基本属性, idtitle ,一个一对多的comments集合,一个一对一的details关联,以及一个多对多的tags集合。

The Post_ Metamodel class is generated as follows: 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";
}

The basic id and title attributes, as well as the one-to-one details association, are represented by a SingularAttribute while the comments and tags collections are represented by the JPA ListAttribute .基本idtitle属性以及一对一的details关联由SingularAttribute表示,而commentstags集合由 JPA ListAttribute表示。

PostDetails entity Metamodel PostDetails 实体元模型

The PostDetails entity 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 SingularAttribute in the associated PostDetails_ Metamodel class:所有实体属性都将由关联PostDetails_ Metamodel 类中的 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 entity Metamodel PostComment 实体元模型

The PostComment is 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 SingularAttribute in the associated PostComments_ Metamodel class:而且,所有实体属性都由关联PostComments_ Metamodel 类中的 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";
}

Using the JPA Criteria Metamodel使用 JPA 标准元模型

Without the JPA Metamodel, a Criteria API query that needs to fetch the PostComment entities filtered by their associated Post title would look like this:如果没有 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();

Notice that we used the post String literal when creating the Join instance, and we used the title String literal when referencing the Post title .请注意,我们在创建Join实例时使用了post String 字面量,而在引用Post title时我们使用了title String 字面量。

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

Or, let's say we want to fetch a DTO projection while filtering the Post title and the PostDetails createdOn attributes.或者,假设我们想要在过滤Post titlePostDetails createdOn属性时获取 DTO 投影。

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?酷,对吧?

For eclipselink, only the following dependency is sufficient to generate metamodel.对于eclipselink,只需要以下依赖就足以生成元模型。 Nothing else is needed.不需要其他任何东西。

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

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.如果是 IDE Eclipse 1. 转到 Project->Properties->Java Compiler->Annotation Processing 并启用它。 2. Expand Annotation Processing->Factory Path-> Add External Jar add Hibernate JPA 2 Metamodel Generator jar check the newly added jar and say OK. 2. 展开Annotation Processing->Factory Path-> Add External Jar add Hibernate JPA 2 Metamodel Generator jar 勾选新添加的jar并说OK。 Clean and Build done!清洁和构建完成!

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

Ok, based on what I have read here, I did it with EclipseLink this way and I did not need to put the processor dependency to the project, only as an annotationProcessorPath element 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>

See this post for a minimal configuration with maven and how to deal with generated JPA metamodel source code in IDEs.有关 maven 的最小配置以及如何在 IDE 中处理生成的 JPA 元模型源代码,请参阅这篇文章

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

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