Bu çok yaygın bir soru olduğu için bu cevabın dayandığı bu makaleyi yazdım .
Uygulamamızın aşağıdakileri kullandığını varsayalım Post , PostComment, PostDetailsve Tagbir tane çoğa oluşturan kişiler, bire-bir ve birçok çoğa tablo ilişkileri :

JPA Ölçütleri Metamodeli nasıl oluşturulur?
hibernate-jpamodelgenHazırda ORM tarafından sağlanan alet proje varlıkları tarama ve JPA Kriterlerini Metamodel üretmek için kullanılabilir. Tek yapmanız gereken tek şey aşağıdaki ekleyin annotationProcessorPathiçin maven-compiler-pluginMaven içinde pom.xmlyapılandırma dosyasının:
<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>
Şimdi, proje derlendiğinde, targetklasörde aşağıdaki Java sınıflarının oluşturulduğunu görebilirsiniz:
> tree target/generated-sources/
target/generated-sources/
└── annotations
└── com
└── vladmihalcea
└── book
└── hpjp
└── hibernate
├── forum
│ ├── PostComment_.java
│ ├── PostDetails_.java
│ ├── Post_.java
│ └── Tag_.java
Etiket varlığı Metamodel
Eğer Tagaşağıdaki gibi varlık eşleştirilmiş:
@Entity
@Table(name = "tag")
public class Tag {
@Id
private Long id;
private String name;
}
Tag_Metamodel sınıfı böyle oluşturulur:
@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";
}
SingularAttributeTemel için kullanılır idve name TagJPA varlık öznitelikleri.
Gönderi varlığı Metamodel
PostVarlık böyle eşleştirilmiş:
@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<>();
}
PostVarlık iki temel özelliklere sahiptir, idve title, bire-birçok commentskoleksiyon, bire-bir detailsilişki ve bir çok-çok sayıda tagskoleksiyon.
Post_Aşağıdaki gibi Metamodel sınıfı oluşturulur:
@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";
}
Temel idve titleözniteliklerin yanı sıra bire bir detailsilişki, bir SingularAttributesüre ile temsil edilir commentsve tagskoleksiyonları JPA tarafından temsil edilir ListAttribute.
PostDetails varlık Metamodel
PostDetailsVarlık böyle eşleştirilmiş:
@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;
}
Tüm varlık öznitelikleri SingularAttribute, ilişkili PostDetails_Metamodel sınıfında JPA tarafından temsil edilecektir :
@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 varlığı Metamodel
Aşağıdaki PostCommentgibi eşlenir:
@Entity
@Table(name = "post_comment")
public class PostComment {
@Id
private Long id;
@ManyToOne(fetch = FetchType.LAZY)
private Post post;
private String review;
}
Ve tüm varlık öznitelikleri SingularAttribute, ilişkili PostComments_Metamodel sınıfında JPA tarafından temsil edilir :
@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 Ölçütleri Metamodelini Kullanma
JPA Metamodel olmadan, PostCommentilişkili Postbaşlıklarına göre filtrelenen varlıkları getirmesi gereken bir Criteria API sorgusu şu şekilde görünür:
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();
Kullandığımız bu Bildirimi postoluştururken dize Joinörneği ve kullandığımız titlebaşvururken dize Post title.
JPA Metamodel, aşağıdaki örnekte gösterildiği gibi, varlık özniteliklerini sabit kodlamamıza izin verir:
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 gibi bir kod tamamlama aracı kullanıyorsanız, JPA Criteria API sorguları yazmak çok daha kolaydır. Check out bu makaleyi Codota IDE eklentisi hakkında daha fazla ayrıntı için.
Ya da, hadi biz bir getirme istediğini söylüyorsun DTO projeksiyonunu filtreleme süre Post titleve PostDetails createdOnözelliklerini.
Metamodeli birleştirme özniteliklerini oluştururken ve ayrıca DTO projeksiyon sütunu takma adlarını oluştururken veya filtrelememiz gereken varlık özniteliklerine referans verirken kullanabiliriz:
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();
Harika, değil mi?