104

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

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

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

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

4

7 回答 7

91

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

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

EclipseLink

休眠

OpenJPA

数据核


最新的 Hibernate 实现位于:

较旧的 Hibernate 实现位于:

于 2010-06-14T13:59:13.710 回答
48

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

休眠

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

Hibernate 作为依赖项

    <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 似乎需要额外的元素<openjpa.metamodel>true<openjpa.metamodel>

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>
于 2012-06-28T13:27:43.890 回答
20

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

  1. 在Package Explorer中选择您的项目
  2. 转到属性-> JPA对话框
  3. 从规范元模型(JPA 2.0)组中选择源文件夹
  4. 单击应用按钮以在选定的源文件夹中生成元模型类

在此处输入图像描述

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

也见这里

于 2012-06-28T14:06:19.233 回答
13

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

JPA 标准元模型

如何生成 JPA 标准元模型

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

SingularAttribute用于基本和idJPAname Tag实体属性。

发布实体元模型

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实体有两个基本属性,一对多集合、一对一关联id和多对多集合。titlecommentsdetailstags

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

基本的idtitle属性,以及一对一的details关联,都由SingularAttributewhile表示,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
}

所有实体属性都将由SingularAttribute关联PostDetails_元模型类中的 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 实体元模型

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
}

并且,所有实体属性都由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";
}

使用 JPA 标准元模型

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

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实例时使用了titleString 文字,而在引用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();

或者,假设我们想要在过滤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();

很酷,对吧?

于 2020-04-01T11:07:39.237 回答
8

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

    <dependency>
        <groupId>org.eclipse.persistence</groupId>
        <artifactId>org.eclipse.persistence.jpa.modelgen.processor</artifactId>
        <version>2.5.1</version>
        <scope>provided</scope>
    </dependency>
于 2014-06-09T11:47:46.517 回答
6

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

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

如果是 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。清洁和建造完成!

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

于 2016-07-13T09:35:51.673 回答
1

好的,根据我在这里阅读的内容,我是通过这种方式使用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>
于 2020-05-29T18:24:06.393 回答