[Spring JPA #7] JPA Fetch
| JPA Fetch
JPA Fetch는 연관 관계의 엔티티를 어떻게 가져올 것인지를 정하는 정책입니다. Eager(초기) 혹은 Lazy(나중) 옵션을 지정하여 어떻게 연관 관계의 엔티티를 가져올 것인지를 정할 수 있습니다.
| JPA Fetch 예제 @OneToMany
프로젝트 구조
├── src
│ ├── main
│ │ ├── java
│ │ │ └── com
│ │ │ └── tutorial
│ │ │ └── springbootjpa
│ │ │ ├── Account.java
│ │ │ ├── Address.java
│ │ │ ├── Comment.java
│ │ │ ├── JpaRunner.java
│ │ │ ├── Post.java
│ │ │ ├── SpringBootJpaApplication.java
│ │ │ └── Study.java
│ │ └── resources
│ │ ├── application.properties
│ │ ├── static
│ │ └── templates
의존성 관리
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
DB 저장 상태
springboot=# select * from post;
id | title
----+-------------------
1 | Spring Data Title
(1 row)
springboot=# select * from comment;
id | comment | post_id
----+-------------------+---------
2 | Yes it is | 1
3 | Great Spring Data | 1
(2 rows)
소스 코드
@SpringBootApplication
public class SpringBootJpaApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBootJpaApplication.class, args);
}
}
@Entity
public class Comment {
@Id
@GeneratedValue
private Long id;
private String comment;
@ManyToOne
private Post post;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getComment() {
return comment;
}
public void setComment(String comment) {
this.comment = comment;
}
public Post getPost() {
return post;
}
public void setPost(Post post) {
this.post = post;
}
}
@Entity
public class Post {
@Id
@GeneratedValue
private Long id;
private String title;
@OneToMany(mappedBy = "post", cascade = CascadeType.ALL)
private Set<Comment> comments = new HashSet<>();
public void addComment(Comment comment){
this.comments.add(comment);
comment.setPost(this);
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public Set<Comment> getComments() {
return comments;
}
public void setComments(Set<Comment> comments) {
this.comments = comments;
}
}
@Component
@Transactional
public class JpaRunner implements ApplicationRunner {
@PersistenceContext
EntityManager entityManager;
@Override
public void run(ApplicationArguments args) throws Exception {
Session session = entityManager.unwrap(Session.class);
Post post = session.get(Post.class, 1l);
System.out.println("==================");
System.out.println(post.getTitle());
}
}
- 위와 같이 데이터를 가져올 시, 연관 관계를 가지는 Commnet 엔티티에 대한 정보는 로딩하지 않고 Post 엔티티에 대한 정보만 가져오게 됩니다. 왜냐하면 @OneToMany 어노테이션은 FetchType.LAZY 가 Default로 설정되어 있기 때문에 Lazy 로딩이 되기 때문입니다.
결과 화면
Hibernate:
select
post0_.id as id1_2_0_,
post0_.title as title2_2_0_
from
post post0_
where
post0_.id=?
만일
@OneToMany(mappedBy = "post", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
private Set<Comment> comments = new HashSet<>();
와 같이 FetchType.EAGER 옵션을 주게 될 경우 Post 엔티티와 연관된 모든 Comment 엔티티에 대한 정보를 가져오게 됩니다.
결과 화면
Hibernate:
select
post0_.id as id1_2_0_,
post0_.title as title2_2_0_,
comments1_.post_id as post_id3_1_1_,
comments1_.id as id1_1_1_,
comments1_.id as id1_1_2_,
comments1_.comment as comment2_1_2_,
comments1_.post_id as post_id3_1_2_
from
post post0_
left outer join
comment comments1_
on post0_.id=comments1_.post_id
where
post0_.id=?
| JPA 예제 ManyToOne
소스 코드
@Component
@Transactional
public class JpaRunner implements ApplicationRunner {
@PersistenceContext
EntityManager entityManager;
@Override
public void run(ApplicationArguments args) throws Exception {
Session session = entityManager.unwrap(Session.class);
Comment comment = session.get(Comment.class, 2l);
System.out.println("==================");
System.out.println(comment.getComment());
System.out.println(comment.getPost().getTitle());
}
}
- 위와 같이 Comment 엔티티를 가져올 경우 자동적으로 그와 매핑되어 있는 Post 엔티티에 대한 정보를 가져오게 됩니다. 왜냐하면 매핑정보에 저장되어 있는 @ManyToOne 어노테이션은 FetchType.EAGER가 기본적으로 설정되어 있기 때문에 매핑되어 있는 연관된 엔티티에 대한 데이터를 로딩하기 때문입니다.
결과 화면
Hibernate:
select
comment0_.id as id1_1_0_,
comment0_.comment as comment2_1_0_,
comment0_.post_id as post_id3_1_0_,
post1_.id as id1_2_1_,
post1_.title as title2_2_1_
from
comment comment0_
left outer join
post post1_
on comment0_.post_id=post1_.id
where
comment0_.id=?
==================
Yes it is
Spring Data Title
'Spring Data > Spring Data JPA' 카테고리의 다른 글
[Spring JPA #11] 스프링 데이터 리포지터리 인터페이스 정의하기(Spring Repository Interface) (0) | 2021.03.25 |
---|---|
[Spring JPA #10] 스프링 데이터 Common 리포지터리(Repository) (0) | 2021.03.25 |
[Spring JPA #9] 스프링 데이터 JPA 원리 및 스프링 데이터 구성 요소 (0) | 2021.03.25 |
[Spring JPA #8] JPA Query (0) | 2021.03.25 |
[Spring JPA #6] JPA Cascade (0) | 2021.03.25 |
[Spring JPA #5] JPA 엔티티 상태 (0) | 2021.03.25 |
[Spring JPA #4] JPA 관계 매핑 (0) | 2021.03.25 |
[Spring JPA #3] Entity 매핑 및 Value 타입 매핑 (0) | 2021.03.25 |