Vì đây là một câu hỏi rất phổ biến, tôi đã viết bài báo này , dựa trên câu trả lời này.
Hãy giả sử ứng dụng của chúng tôi sử dụng những điều sau đây Post , PostComment, PostDetails, và Tagcác tổ chức, hình thành nên một one-to-many, one-to-one, và nhiều-nhiều mối quan hệ bảng :

Cách tạo Siêu mô hình tiêu chí JPA
Công hibernate-jpamodelgencụ do Hibernate ORM cung cấp có thể được sử dụng để quét các thực thể dự án và tạo Siêu mô hình tiêu chí JPA. Tất cả những gì bạn cần làm là thêm phần sau annotationProcessorPathvào tệp cấu hình maven-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>
Bây giờ, khi dự án được biên dịch, bạn có thể thấy rằng trong targetthư mục, các lớp Java sau được tạo:
> tree target/generated-sources/
target/generated-sources/
└── annotations
└── com
└── vladmihalcea
└── book
└── hpjp
└── hibernate
├── forum
│ ├── PostComment_.java
│ ├── PostDetails_.java
│ ├── Post_.java
│ └── Tag_.java
Thẻ Metamodel thực thể
Nếu Tagthực thể được ánh xạ như sau:
@Entity
@Table(name = "tag")
public class Tag {
@Id
private Long id;
private String name;
//Getters and setters omitted for brevity
}
Các Tag_ Metamodel được tạo như sau:
@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";
}
Các SingularAttribute được sử dụng cho các cơ sở idvà name Tagcác thuộc tính thực thể JPA.
Đăng thực thể Metamodel
Các Postthể được ánh xạ như thế này:
@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
}
Thực Postthể có hai thuộc tính cơ bản idvà titlemột-nhiềucomments tập hợp một , detailsliên kết một-một và tagstập hợp nhiều-nhiều .
Các Post_ Metamodel được tạo như sau:
@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";
}
Cơ bản idvà titlecác thuộc tính, cũng như one-to-one detailshiệp hội, được đại diện bởi một SingularAttributetrong khicomments và các tagstập hợp được đại diện bởi JPA ListAttribute.
Thực thể PostDetails Metamodel
Thực PostDetailsthể được ánh xạ như thế này:
@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
}
Tất cả các thuộc tính thực thể sẽ được biểu thị bằng JPA SingularAttributetrong PostDetails_lớp Metamodel được liên kết :
@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";
}
Thực thể PostComment Metamodel
Các PostCommentđược ánh xạ như sau:
@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
}
Và, tất cả các thuộc tính thực thể được đại diện bởi JPA SingularAttributetrong PostComments_lớp Metamodel được liên kết :
@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";
}
Sử dụng siêu mô hình tiêu chí JPA
Nếu không có Siêu mô hình JPA, truy vấn API tiêu chí cần tìm nạp các PostCommentthực thể được lọc theo Posttiêu đề được liên kết của chúng sẽ trông giống như sau:
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();
Lưu ý rằng chúng tôi đã sử dụng postký tự Chuỗi khi tạo Joincá thể và chúng tôi đã sử dụng titleký tự Chuỗi khi tham chiếuPost title .
JPA Metamodel cho phép chúng tôi tránh các thuộc tính thực thể mã hóa cứng, như được minh họa bằng ví dụ sau:
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();
Viết các truy vấn JPA Criteria API dễ dàng hơn nhiều nếu bạn đang sử dụng một công cụ hoàn thành mã như Codota. Kiểm tra bài viết này để biết thêm chi tiết về plugin Codota IDE.
Hoặc, giả sử chúng tôi muốn tìm nạp một phép chiếu DTO trong khi lọc Post titlecác PostDetails createdOnthuộc tính và.
Chúng ta có thể sử dụng Metamodel khi tạo các thuộc tính nối, cũng như khi xây dựng bí danh cột chiếu DTO hoặc khi tham chiếu đến các thuộc tính thực thể mà chúng ta cần lọc:
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();
Tuyệt, phải không?