이것은 매우 일반적인 질문이므로이 답변의 기반이되는이 기사를 작성 했습니다.
하자 우리의 응용 프로그램이 다음을 사용하는 가정 Post
, PostComment
, PostDetails
, 및 Tag
일대를 형성 기관, 일대일 및 다 대다 테이블 관계 :
JPA 기준 메타 모델을 생성하는 방법
hibernate-jpamodelgen
최대 절전 모드 ORM에서 제공하는 도구는 프로젝트 엔티티를 스캔하고 JPA 기준 메타 모델을 생성 할 수 있습니다. Maven 구성 파일 에 다음 annotationProcessorPath
을 추가 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
컬렉션 일대일 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
과 tags
모음은 JPA로 표시된다 ListAttribute
.
PostDetails 엔티티 메타 모델
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
}
모든 엔티티 속성은 SingularAttribute
연관된 PostDetails_
Metamodel 클래스 에서 JPA로 표시됩니다 .
@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 엔티티 메타 모델
은 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
}
그리고 모든 엔티티 속성은 SingularAttribute
연관된 PostComments_
Metamodel 클래스 에서 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";
}
JPA 기준 메타 모델 사용
JPA 메타 모델이 없으면 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 쿼리를 작성하는 것이 훨씬 쉽습니다. Codota IDE 플러그인에 대한 자세한 내용은 이 기사 를 확인하십시오 .
또는,하자 우리가 가져 싶은 말은 DTO 투영을 필터링하는 동안 Post
title
과 PostDetails
createdOn
특성을.
조인 속성을 만들 때뿐만 아니라 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();
멋지죠?