如何生成JPA实体元模型?


94

本着与CriteriaQuery关联的类型安全的精神,JPA 2.0还具有一个API,用于支持实体的元模型表示。

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

编辑:偶然发现了Hibernate JPA 2元模型生成器。但是问题仍然存在,因为我找不到该jar的任何下载链接。

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

Answers:


87

如果有人也知道在Eclipse中进行设置的步骤,那将是非常棒的(我认为这与设置注释处理器一样简单,但您永远不会知道)

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

EclipseLink

冬眠

OpenJPA

数据核


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

较旧的Hibernate实现位于:


1
DataNucleus链接已死。
Karl Richter '18

1
休眠链接也死了
Freelancer

43

请看一下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似乎需要其他元素<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>

3
需要明确的是,生成的东西可以与eclipselink一起使用,即使您使用休眠来生成它,我也无法从netbeans 8生成元模型,而不得不创建一个maven测试项目来生成我的东西
Kalpesh Soni 2014年

@ymajoros因此,是否禁止something is recommended不发言IMHO?我不是代表其他任何人。
金权

1
顺便说一句,请参阅EclipseLink的Sorter答案。这是我使用多年的配置,并且效果很好。stackoverflow.com/questions/3037593/…–
ymajoros

这不是实现具体的我尝试使用Hibernate生成的元模型用的EclipseLink,并得到NullPointerException异常
米哈尔Ziobro

@ymajoros仍然需要一个persistence.xml,不是吗?
晋权

20

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

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

在此处输入图片说明

由于生成的类是标准的,因此这对任何JPA提供程序都适用。

另请参阅此处


有什么办法可以自己开始这个过程吗?这不可靠产生的元模型对我来说
thatsIch

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>


@Barthelomeus您的备注为。EclipseLink 2.5.1+也会为未列出的实体生成元模型类,只需<exclude-unlisted-classes>false</exclude-unlisted-classes>在persisetence.xml中指定
Michele Mariotti

注意的EclipseLink不会产生无persistence.xml
金权

5

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

如果使用Gradle,Maven之类的构建工具,则需要在类路径中具有Hibernate JPA 2元模型生成器jar,而编译器级别> = 1.6就是您所需要的全部构建项目,并且元模型将自动生成。

对于IDE Eclipse 1.进入Project-> Properties-> Java Compiler-> Annotation Processing并启用它。2.展开注释处理->工厂路径->添加外部jar添加Hibernate JPA 2 Metamodel Generator jar检查新添加的jar,然后说确定。清理并完成!

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


就我而言,添加<dependencies> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-jpamodelgen</artifactId> <scope>compile</scope> </dependency> </dependencies>到pom.xml就足够了。
Lu55

使用maven和Eclipse时是否需要两种配置?
Melkor

即使在pom中添加了hibernate-jpamodelgen,我也必须这样做并且它起作用
Freelancer

3

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

假设我们的应用程序使用以下PostPostCommentPostDetails,和Tag实体,形成一到多,一到一个,和许多一对多表关系

JPA标准元模型

如何生成JPA条件元模型

hibernate-jpamodelgenHibernate ORM提供的工具可用于扫描项目实体并生成JPA Criteria Metamodel。您需要做的就是将以下内容添加annotationProcessorPathmaven-compiler-pluginMaven 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 TagJPA实体的属性。

发布实体元模型

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并且title,一到多的comments集合,一个对一个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";
}

基本idtitle属性以及一对一details关联用表示,SingularAttributecommentstags集合用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_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实体元模型

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_Metamodel类中的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按其关联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查询要容易得多。请查看本文以获取有关Codota IDE插件的更多详细信息。

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

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

酷吧?


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>
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.