반응형
1. 지연로딩
엔티티 조회 시 일반 멤버 변수만 먼저 조회되고, 객체(연관관계 엔티티)로 되어 있는 멤버 변수 조회 시, 가짜 객체로 먼저 조회되고, 실제 멤버 변수가 조회될 때, 실제 쿼리를 한번 더 실행시키는 기법이다.
말이 좀 어려운데, 간단한 코드로 보면
@Entity
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Member{
@Id @GeneratedValue
@Column(name = "member_id")
private Long id;
private String name;
private int age;
// 연관관계 엔티티
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "team_id")
private Team team;
// 생성자
@builder
public Member(String name, int age, Team team){
this.name = name;
this.age = age;
changeTeam(team);
}
public void changeTeam(Team team){
this.team = team;
// Team 엔티티의 멤버 리스트에 해당 멤버 추가
team.getMembers.add(this);
}
}
@Entity
@Getter
@NoArgsConstruntor(aceess = AccessLevel.PROTECTED)
public class Team{
@Id @GeneratedValue
@Column(name = "team_id")
private Long id;
private String name;
@OneToMany(mappedBy = "team")
private List<Member> members = new ArrayList<>();
public void Team(){
this.name = name;
}
}
우선, Member 엔티티를 보자,
id, name, age 처럼 일반 멤버변수들은 Member 엔티티 조회 시, 한번에 조회된다. 하지만, Team 객체는 Member 엔티티에서는 가짜 객체이므로 조회 시, null로 조회될 수는 없으니 '...$HibernateProxy$7ffISbXn' 이런 식으로 조회된다. 그 후 실제 Team의 멤버변수를 조회할 때, Team 멤버변수를 조회하는 쿼리가 수행된다.
2. Junit 테스트 코드
@SpringBootTest
@Transactional
class LazyTest{
@AutoWired
EntityManager em;
private final MemberRepository memberRepository;
private final TeamRepository teamRepository;
// 생성자 주입
public LazyTest(MemberRepository memberRepository
, TeamRepository teamRepository){
this.memberRepository = memberRepository;
this.teamRepository = teamRepository;
}
@Test
public void FetchLazyTest(){
Team manCity = new Team("manchesterCity");
teamRepository.save(manCity);
Member member1 = Member.builder()
.name("KDB")
.age(34)
.team(manCity)
.build();
memberRepository.save(member1);
// Rollback은 진행하지만 Insert 쿼리 수행 시 명시
em.flush();
// Member 엔티티 조회
Member findMember = memberRepository.findMember(1, "KDB");
// 일반 멤버변수는 한번에 조회됨.
System.out.println(findMember.getName()); // KDB
// ...$HibernateProxy$7ffISbXn 이런식으로 가짜 객체가 출력됨
System.out.println(findMember.getTeam().getClass());
// 가짜객체였다가 이때 실제 team의 name을 조회하는 쿼리가 수행됨.
String teamName = findMember.getTeam().getName();
assertThat(teamName).isEqualTo("manchesterCity"); // true
}
}
다음 포스팅은, N + 1 문제를 포스팅해보겠다.
반응형