작성
·
160
1
선생님 먼저 코드를 보여드리고 자세한 내용을 설명 해 드리겠습니다.
@Entity
public class Member {
@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;
// getter setter 생략
}
@Entity
public class Team {
@Id @GeneratedValue
@Column(name = "TEAM_ID")
private Long id;
private String name;
@OneToMany(mappedBy = "team")
private List<Member> members = new ArrayList<>();
// getter, setter 생략
}
Team team = new Team();
team.setName("teamA");
em.persist(team);
Team team2 = new Team();
team2.setName("teamA");
em.persist(team2);
Member member = new Member();
member.setUsername("member1");
member.setTeam(team);
em.persist(member);
Member member2 = new Member();
member2.setUsername("member1");
member2.setTeam(team2);
em.persist(member2);
em.flush();
em.clear();
Member findMember1 = em.find(Member.class, 3L);
Member findMember2 = em.find(Member.class, 4L);
Team findTeam = em.find(Team.class, 1L);
간단히 Member-Team 은 다대일 매핑이며, Member 는 디폴트인 즉시로딩으로 설정했습니다.
예제 코드를 보면 영속성 컨테스트를 비운뒤에 find() 로 3번 호출 했습니다.
그런데 select문은 총 2번 호출됩니다.
출력을 확인 해보면 Team 을 find() 하는 select문이 생략 되는데 제 추측은 Member 가 즉시로딩으로 되어 있기 때문에
Member를 데이터베이스에서 가져올때 Team 도 영속성 컨텍스트에 추가되고 Team을 find() 할 때는 1차 캐시에서 가져오는 거라 생각이 듭니다.
그런데 생각해보면, 위에서 Member find() 할때도 따로 Team 을 select 하는 쿼리를 사용하지는 않았는데(join 쿼리만 있음)
jpa는 내부적으로 join 하면서 join 한 대상도 영속성 컨텍스트에 자동으로 추가 하는 것인가요.?
답변 1
3
안녕하세요. 햇병아리님^^
와~ 이렇게 자세히 적어주시니 머리속에 쏙쏙 이해가 됩니다. ㅎㅎ
결론부터 말씀드리면 생각하신 내용이 맞습니다.
즉시 로딩이기 때문에 JPA는 member 엔티티를 find()로 조회하면서 연관된 team 엔티티도 함께 데이터베이스에서 조회를 해버립니다. 그리고 중요한 사실은 JPA에서 엔티티로 조회되면 바로 영속성 컨텍스트에 관리된다는 사실입니다. 그래서 member는 물론이고 team도 함께 영속성 컨텍스트에 관리됩니다.
따라서 이후에 해당 team을 조회하면, 영속성 컨텍스트에서 바로 조회를 하게 됩니다.
감사합니다.