本着与CriteriaQuery相关联的类型安全的精神,JPA 2.0还有一个API来支持实体的Metamodel表示。
有没有人知道这个API的全功能实现(生成Metamodel而不是手动创建元模型类)?如果有人也知道在Eclipse中设置它的步骤,那将是非常棒的(我认为它就像设置注释处理器一样简单,但你永远不知道)。
编辑: 偶然发现了Hibernate JPA 2 Metamodel Generator 。但问题仍然存在,因为我找不到任何jar的下载链接。
编辑2: 自从我提出这个问题以来已经过了一段时间,但我想我会回来并添加Hibernate JPA Model Generator project on SourceForge的链接
答案 0 :(得分:84)
如果有人也知道在Eclipse中设置它的步骤会很棒(我假设它就像设置注释处理器一样简单,但你永远不知道)
是的。以下是各种JPA 2.0实现的实现和说明:
org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor
org.apache.openjpa.persistence.meta.AnnotationProcessor6
org.datanucleus.jpa.JPACriteriaProcessor
最新的Hibernate实现可在以下网址获得:
较旧的Hibernate实现位于:
答案 1 :(得分:40)
最推荐使用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.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需要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集成。
这应该适用于任何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,此答案基于此。
假设我们的应用程序使用以下Post
,PostComment
,PostDetails
和Tag
实体,它们构成一对多,一对一,以及多对多table relationships:
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
用于基本的id
和name
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
实体具有两个基本属性,id
和title
,一对多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
表示,而SingularAttribute
和comments
集合由JPA tags
表示。
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_
@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元模型的情况下,需要提取按@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
title
和PostDetails
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>