如何生成JPA 2.0元模型?

时间:2010-06-14 13:32:58

标签: java jpa jpa-2.0 metamodel annotation-processing

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

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

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

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

7 个答案:

答案 0 :(得分:84)

  

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

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

的EclipseLink

休眠

OpenJPA的

DataNucleus将


最新的Hibernate实现可在以下网址获得:

较旧的Hibernate实现位于:

答案 1 :(得分:40)

修订版(2014年3月)

请查看jpa-metamodels-with-maven

休眠

最推荐使用Hibernate。

我不判断这些实现上的任何特性/功能/可用性/稳定性。上述声明仅关注我构建的maven用法。

<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.hibernate.jpamodelgen.JPAMetaModelEntityProcessor</processor>
        </processors>
      </configuration>
    </execution>
  </executions>
  <dependencies>
    <dependency>        
      <groupId>org.hibernate</groupId>
      <artifactId>hibernate-jpamodelgen</artifactId>
      <version>4.3.4.Final</version>
    </dependency>
  </dependencies>
</plugin>

OpenJPA的

OpenJPA似乎需要额外的元素<openjpa.metamodel>true<openjpa.metamodel>

<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>2.3.0</version>
    </dependency>
  </dependencies>
</plugin>

的EclipseLink

EclipseLink需要persistence.xml

<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.eclipse.persistence.internal.jpa.modelgen.CanonicalModelProcessor</processor>
        </processors>
      </configuration>
    </execution>
  </executions>
  <dependencies>
    <dependency>
      <groupId>org.eclipse.persistence</groupId>
      <artifactId>org.eclipse.persistence.jpa.modelgen.processor</artifactId>
      <version>2.5.1</version>
    </dependency>
  </dependencies>
</plugin>

<强> ========================================

对于Apache Maven用户,

以下简单配置似乎有效。 (使用旧的maven-compiler-plugin;更新。

<!-- This method doesn't work with newest maven-compiler-plugin -->
<!-- But if it's ok to work with old maven-compiler-plugin -->
<!-- This is the best method -->
<!-- There is no other required configurations -->
<!-- We don't even require to config any processor names -->

<project>
  <build>

    <extensions>
      <extension>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-jpamodelgen</artifactId>
        <version>1.3.0.Final</version>
      </extension>
    </extensions>

    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>2.5.1</version> <!-- this is critical -->
        <configuration>
          <source>1.6</source>
          <target>1.6</target>
        </configuration>
      </plugin>

    </plugins>
  </build>
</project>

你可以用“mvn compiler:compile”

运行它

<强>更新

请注意,此方法仅适用于那些旧的maven-compiler-plugin。检查代码中的版本。

答案 2 :(得分:17)

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

  1. Package Explorer
  2. 中选择您的项目
  3. 转到属性 - &gt; JPA 对话框
  4. Canonical元模型(JPA 2.0)组中选择源文件夹
  5. 单击应用按钮以在所选源文件夹
  6. 中生成元模型类

    enter image description here

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

    另见here

答案 3 :(得分:6)

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

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

答案 4 :(得分:4)

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

对于像Gradle,Maven这样的构建工具,你需要在类路径和编译器级别&gt; = 1.6中拥有Hibernate JPA 2 Metamodel Generator jar,这就是你需要构建项目和元模型将自动生成。

对于IDE Eclipse 1.转到项目 - >属性 - > Java编译器 - &gt;注释处理并启用它。 2.展开注释处理 - &gt;工厂路径 - &gt;添加外部Jar添加Hibernate JPA 2 Metamodel Generator jar检查新添加的jar并说好。清洁和建造完成!

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

答案 5 :(得分:3)

由于这是一个非常常见的问题,所以我写了this article,此答案基于此。

假设我们的应用程序使用以下PostPostCommentPostDetailsTag实体,它们构成一对多,一对一,以及多对多table relationships

JPA Criteria Metamodel

如何生成JPA标准元模型

Hibernate ORM提供的hibernate-jpamodelgen工具可用于扫描项目实体并生成JPA Criteria Metamodel。您需要做的就是将以下annotationProcessorPath添加到Maven maven-compiler-plugin配置文件中的pom.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>

现在,在编译项目时,您可以看到在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集合,一对一{{1} }关联,以及多对多details集合。

tags元模型类的生成如下:

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"; } id属性以及一对一title关联由details表示,而SingularAttributecomments集合由JPA tags表示。

PostDetails实体元模型

ListAttribute实体的映射如下:

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 } 元模型类中的JPA SingularAttribute表示:

PostDetails_

PostComment实体元模型

@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 @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 } 元模型类中的JPA SingularAttribute表示:

PostComments_

使用JPA标准元模型

在没有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"; } 关联标题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();

请注意,我们在创建post实例时使用了Join字符串,而在引用title Post时使用了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();

如果使用的是诸如Codota之类的代码完成工具,则编写JPA Criteria API查询要容易得多。请查看this article,以获取有关Codota IDE插件的更多详细信息。

或者,假设我们要在过滤Post titlePostDetails createdOn属性的同时获取DTO projection

我们可以在创建联接属性,构建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();

很酷,对吧?

答案 6 :(得分:0)

好吧,根据我在这里所读的内容,我是通过 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>