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à Tag
cá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-jpamodelgen
cụ 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 annotationProcessorPath
vào tệp cấu hình maven-compiler-plugin
Maven 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 target
thư 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 Tag
thự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ở id
và name
Tag
các thuộc tính thực thể JPA.
Đăng thực thể Metamodel
Các Post
thể đượ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 Post
thể có hai thuộc tính cơ bản id
và title
một-nhiềucomments
tập hợp một , details
liên kết một-một và tags
tậ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 id
và title
các thuộc tính, cũng như one-to-one details
hiệp hội, được đại diện bởi một SingularAttribute
trong khicomments
và các tags
tập hợp được đại diện bởi JPA ListAttribute
.
Thực thể PostDetails Metamodel
Thực PostDetails
thể đượ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 SingularAttribute
trong 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 SingularAttribute
trong 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 PostComment
thực thể được lọc theo Post
tiê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 post
ký tự Chuỗi khi tạo Join
cá thể và chúng tôi đã sử dụng title
ký 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
title
các PostDetails
createdOn
thuộ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?