[英]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 实现的实现和说明:
org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor
org.apache.openjpa.persistence.meta.AnnotationProcessor6
org.datanucleus.jpa.JPACriteriaProcessor
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 。
org.hibernate.org:hibernate-jpamodelgen
.org.hibernate.org:hibernate-jpamodelgen
。org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor
.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>
org.apache.openjpa:openjpa
.org.apache.openjpa:openjpa
。org.apache.openjpa.persistence.meta.AnnotationProcessor6
.org.apache.openjpa.persistence.meta.AnnotationProcessor6
。<openjpa.metamodel>true<openjpa.metamodel>
. <openjpa.metamodel>true<openjpa.metamodel>
。 <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>
<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>
org.eclipse.persistence:org.eclipse.persistence.jpa.modelgen.processor
.org.eclipse.persistence:org.eclipse.persistence.jpa.modelgen.processor
。org.eclipse.persistence.internal.jpa.modelgen.CanonicalModelProcessor
.org.eclipse.persistence.internal.jpa.modelgen.CanonicalModelProcessor
。persistence.xml
. persistence.xml
。 <dependencies>
<dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>org.eclipse.persistence.jpa.modelgen.processor</artifactId>
<scope>provided</scope>
</dependency>
<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:datanucleus-jpa-query
。org.datanucleus.jpa.query.JPACriteriaProcessor
.org.datanucleus.jpa.query.JPACriteriaProcessor
。 <dependencies>
<dependency>
<groupId>org.datanucleus</groupId>
<artifactId>datanucleus-jpa-query</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
<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 集成的自己的元模型生成器。
This should work on any JPA provider as the generated classes are standard.这应该适用于任何 JPA 提供程序,因为生成的类是标准的。
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:假设我们的应用程序使用以下
Post
、 PostComment
、 PostDetails
和Tag
实体,它们形成一对多、一对一和多对多表关系:
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
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
用于基本的id
和name
Tag
JPA 实体属性。
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
实体有两个基本属性, id
和title
,一个一对多的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
.基本
id
和title
属性以及一对一的details
关联由SingularAttribute
表示,而comments
和tags
集合由 JPA ListAttribute
表示。
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";
}
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";
}
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
title
和PostDetails
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>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.