스프링 데이터 JPA-04.Fetch, 쿼리
JPA 프로그래밍 6. Fetch
연관 관계의 엔티티를 어떻게 가져올 것인가? 지금(Eager)? 나중에(Lazy)?
- @OneToMany의 기본값은 Lazy
- @ManyToOne의 기본값은 Eager
포스트(@OneToMany)에 대한 정보를 가져올 때, 코멘트에 대한 정보는 가져오지 않는다. (필요하지도 않을 수도 있는데, 몇건이 될지도 모르는 코멘트들에 대한 정보 안가져옴, 정말 사용해야 한다면 그 시점에서 가져온다.)
근데 반대로 코멘트(@ManyToOne)에 대한 정보를 가져올때는, 포스트에 대한 정보는 가져온다. (1건 이기 때문에 어떻게 생각하면 합리적)
기본적으로 설정된 것을 설정을 통해서 변경이 가능하다.
ex.@OneToMany(mappedBy = “post”, cascade = CascadeType.ALL, fetch = FetchType.EAGER)
구현 및 설명
Post post = session.get(Post.class, 1l); // 1l (1 Long type)
System.out.println("======= Post ========");
System.out.println(post.getTitle());
게시글 번호가 1인 것을 조회할때 코멘트는 가져오지 않는다.
하지만 게시글 번호가 2인 코멘트들도 사용해야 한다면 가져오는 것을 확인할 수 있다.
Session session = entityManager.unwrap(Session.class);
//session.save(post);
Post post = session.get(Post.class, 2l);
System.out.println("======= Post ========");
System.out.println(post.getTitle());
post.getComments().forEach(c-> {
System.out.println("======== comment ========");
System.out.println(c.getComment());
});
System.out.println("======== print =========");
실행결과
Hibernate:
select
post0_.id as id1_2_0_,
post0_.title as title2_2_0_
from
post post0_
where
post0_.id=?
======= Post ========
Jpa 공부중...
Hibernate:
select
comments0_.post_id as post_id3_1_0_,
comments0_.id as id1_1_0_,
comments0_.id as id1_1_1_,
comments0_.comment as comment2_1_1_,
comments0_.post_id as post_id3_1_1_
from
comment comments0_
where
comments0_.post_id=?
======== comment ========
그러게 말이에요..
======== comment ========
언제 공부는 끝나시나요..
======== print =========
JPA 프로그래밍 7. 쿼리
JPQL (HQL)
- Java Persistence Query Language / Hibernate Query Language
- 데이터베이스 테이블이 아닌, 엔티티 객체 모델 기반으로 쿼리 작성.
- JPA 또는 하이버네이트가 해당 쿼리를 SQL로 변환해서 실행함.
- https://docs.jboss.org/hibernate/orm/5.2/userguide/html_single/Hibernate_User_Guide.html#hql
- 단점 : 타입 세이프하지 않다. 문자열 쿼리기 때문에.
@PersistenceContext // jpa 가장 핵심적인 빈
EntityManager entityManager;
@Override
public void run(ApplicationArguments args) {
TypedQuery<Post> query = entityManager.createQuery("SELECT p from Post As p", Post.class);
List<Post> posts = query.getResultList();
posts.forEach(System.out::print);
// toString() 구현 시 comment는 뺌. (comment 넣는다면 필요하니까 toString 사용시 comment도 같이 조회됨
}
Hibernate:
select
post0_.id as id1_2_,
post0_.title as title2_2_
from
post post0_
Post{id=1, title='Jpa 공부중...}Post{id=2, title='Jpa 공부중...}
Criteria
- 타입 세이프 쿼리
- https://docs.jboss.org/hibernate/orm/5.2/userguide/html_single/Hibernate_User_Guide.html#criteria
@Override
public void run(ApplicationArguments args) {
// 타입세이프 쿼리, 문자열이 하나도 들어가지 않는다.
CriteriaBuilder builder = entityManager.getCriteriaBuilder();
CriteriaQuery<Post> criteria = builder.createQuery(Post.class);
Root<Post> root = criteria.from(Post.class);
criteria.select(root);
List<Post> posts = entityManager.createQuery(criteria).getResultList();
posts.forEach(System.out::print);
}
실행결과 동일.
또한 마이바티스 처럼 한곳에다 쿼리를 선언해놓고 호출, 쿼리 이름으로 사용한다던가 등이 가능
Native Query
- SQL 쿼리 실행하기
- https://docs.jboss.org/hibernate/orm/5.2/userguide/html_single/Hibernate_User_Guide.html#sql
@PersistenceContext // jpa 가장 핵심적인 빈
EntityManager entityManager;
@Override
public void run(ApplicationArguments args) {
List<Post> posts = entityManager
.createNativeQuery("SELECT * FROM Post", Post.class)
.getResultList();
posts.forEach(System.out::print);
}
실행결과
Hibernate:
SELECT
*
FROM
Post
Post{id=1, title='Jpa 공부중...}Post{id=2, title='Jpa 공부중...}