지연 로딩 LAZY을 사용해서 프록시로 조회
Member.java
@Entity
@Table
@Getter
@Setter
public class Member extends BaseEntity{
@Id @GeneratedValue
@Column(name = "MEMBER_ID")
private Long id;
@Column(name = "USERNAME")
private String username;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "TEAM_ID")
private Team team;
}
예제
Main.java
// Team 생성 및 영속화
Team team = new Team();
team.setName("teamA");
em.persist(team);
// Member 생성 및 팀 연관 관계 설정 후 영속화
Member member1 = new Member();
member1.setUsername("member1");
member1.setTeam(team);
em.persist(member1);
em.flush();
em.clear();
Member m = em.find(Member.class, member1.getId()); // 프록시
System.out.println("m = " + m.getTeam().getClass());
// 트랜잭션 커밋
tx.commit();
- @ManyToOne(fetch = FetchType.LAZY) 어노테이션 설정하면, 프록시 타입으로 가져온다는 개념이다.
- Member 만 딱 조회되고 Team 은 프록시로 조회된걸 알 수 있다.
- m = class hellojpa.Team$HibernateProxy$wIMSF5gC
Member m = em.find(Member.class, member1.getId()); // 프록시
System.out.println("m = " + m.getTeam().getClass());
m.getTeam().getName(); // Team 조회 쿼리 실행 시점 , 초기화
즉시 로딩을 사용해서 함께 조회
예제
Member.java
@Entity
@Table
@Getter
@Setter
public class Member extends BaseEntity{
@Id @GeneratedValue
@Column(name = "MEMBER_ID")
private Long id;
@Column(name = "USERNAME")
private String username;
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "TEAM_ID")
private Team team;
}
- 조회될때 같이 조회되는거 (쿼리 한번에 실행됨)
실행쿼리
select
member0_.MEMBER_ID as member_i1_3_0_,
member0_.createdBy as createdb2_3_0_,
member0_.createdDate as createdd3_3_0_,
member0_.lastModifiedBy as lastmodi4_3_0_,
member0_.lastModifiedDate as lastmodi5_3_0_,
member0_.TEAM_ID as team_id7_3_0_,
member0_.USERNAME as username6_3_0_,
team1_.TEAM_ID as team_id1_7_1_,
team1_.createdBy as createdb2_7_1_,
team1_.createdDate as createdd3_7_1_,
team1_.lastModifiedBy as lastmodi4_7_1_,
team1_.lastModifiedDate as lastmodi5_7_1_,
team1_.name as name6_7_1_
from
Member member0_
left outer join
Team team1_
on member0_.TEAM_ID=team1_.TEAM_ID
where
member0_.MEMBER_ID=?
프록시와 즉시로딩 주의
- 가급적 지연 로딩만 사용(특히 실무에서)
- 즉시 로딩을 적용하면 예상하지 못한 SQL 발생
- 즉시 로딩은 JPQL에서 N + 1 문제를 일으킨다
- @ManyToOne, @OneToOne은 기본이 즉시 로딩 => LAZY 로 설정
- @OneToMany, @ManyToMany 는 기본이 지연로딩
- 프록시 방법을 쓰면 죄다 조인되서 나중에 속도 엄청 느려져서 성능면에서 안좋음!!!!!
*N+1 문제 일으키는 것에 대한 해결? 방안은 뒤에서 다시 다룰거임, 근데 실무에서는 지연 로딩만 사용하는게 좋다!*
결론
- JPQL fetch 조인이나, 엔티티 그래프 기능을 사용해라 (뒤에서 설명)
- 즉시 로딩은 상상하지 못한 쿼리가 나간다.
- 실무에서 즉시 로딩을 사용하지 마라
'Spring > Spring JPA' 카테고리의 다른 글
실습 5 - 연관관계 관리 (0) | 2024.03.20 |
---|---|
영속성 전이 : CASCADE와 고아 객체 (0) | 2024.03.20 |
프록시 (0) | 2024.03.20 |
실습 4 - 상속관계 매핑 (0) | 2024.03.19 |
고급 매핑 - Mapped Supercalss (0) | 2024.03.19 |