반응형

[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


https://www.inflearn.com/course/스프링-데이터-jpa


반응형

이 글을 공유하기

댓글

Designed by JB FACTORY