예제 시나리오
- 회원과 팀이 있다.
- 회원은 하나의 팀에만 소속될 수 있다.
- 회원과 팀은 다대일 관계이다.
객체를 테이블에 맞추어 모델링
@Entity
public class Member {
@Id
@GeneratedValue
@Column(name = "MEMBER_ID")
private Long id;
@Column(name = "TEAM_ID")
private Long teamId;
private String name;
}
@Entity
public class Team {
@Id
@GeneratedValue
@Column(name = "TEAM_ID")
private Long id;
private String name;
}
객체를 테이블에 맞추어 모델링을 하면 외래키 식별자를 직접 다뤄야 한다.
- 객체자향적인 설계가 아님
저장
EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");
EntityManager em = emf.createEntityManager();
EntityTransaction tx = em.getTransaction();
tx.begin();
try {
//객체 저장
Team team = new Team();
team.setName("TeamA");
em.persist(team);
Member member = new Member();
member.setName("harris");
member.setTeamId(team.getId());
em.persist(member);
}
조회
Member findMember = em.find(Member.class, member.getId());
Team findTeam = em.find(Team.class, findMember.getTeamId());
System.out.println("findTeamName" + findTeam.getName());
객체를 데이터 중심으로 모델링하면 협력 관계를 만들 수 없다!!
- 테이블은 외래키로 조인을 사용해서 연관된 테이블을 찾는다.
- 객체는 참조를 사용해서 연관된 객체를 찾는다.
- 테이블과 객체 사이에는 이런 큰 간격이 있다.
객체지향 모델링
코드 상 큰 차이는 없고, 멤버의 필드로 teamId 대신 team을 갖게한다.
@Entity
public class Member {
@Id
@GeneratedValue
@Column(name = "MEMBER_ID")
private Long id;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "TEAM_ID")
private Team team;
private String name;
}
이렇게 변화되면 보다 객체지향적으로 접근이 가능하다.
//저장
Team team = new Team();
team.setName("TeamA");
em.persist(team);
Member member = new Member();
member.setName("harris");
member.setTeam(team);
em.persist(member);
em.flush();
em.clear();
//조회
Member findMember = em.find(Member.class, member.getId());
System.out.println("findTeamName" + findMember.getTeam().getName());
- 저장, 조회 시 teamId로 세팅, 조회하는 것에서 team을 직접 참조하는 것을 확인 할 수 있다.
FetchType.EAGER vs FetchType.LAZY
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "TEAM_ID")
private Team team;
위의 코드에서 객체간의 관계를 설정할 때 FetchType을 설정한 것을 볼 수 있다.
아래는 Eager, Lazy 로 세팅했을 때의 발생하는 쿼리이다.
LAZY
Hibernate:
select
member0_.MEMBER_ID as MEMBER_I1_0_0_,
member0_.name as name2_0_0_,
member0_.TEAM_ID as TEAM_ID3_0_0_
from
Member member0_
where
member0_.MEMBER_ID=?
Hibernate:
select
team0_.TEAM_ID as TEAM_ID1_1_0_,
team0_.name as name2_1_0_
from
Team team0_
where
team0_.TEAM_ID=?
EAGER
Hibernate:
select
member0_.MEMBER_ID as MEMBER_I1_0_0_,
member0_.name as name2_0_0_,
member0_.TEAM_ID as TEAM_ID3_0_0_,
team1_.TEAM_ID as TEAM_ID1_1_1_,
team1_.name as name2_1_1_
from
Member member0_
left outer join
Team team1_
on member0_.TEAM_ID=team1_.TEAM_ID
where
member0_.MEMBER_ID=?
LAZY의 경우는 member를 조회할 때 team을 바로 조회하지않고 team이 필요한 시점에 조회한다.
EAGER의 경우에는 member를 조회할 때 team도 한 번에 조회를 한다.
두 전략 모두 장단점이 있기 때문에 이를 잘 알고 사용해야 한다!!
Ref : 김영한님 inflearn 강의
'DB' 카테고리의 다른 글
Real MySQL 1장 ~ 3장 (0) | 2022.05.23 |
---|---|
JPA - 프록시 (0) | 2021.09.12 |
JPA - @MappedSuperclass (0) | 2021.09.11 |
JPA - 다양한 연관관계 매핑 (0) | 2021.09.11 |
JPA - 양방향 연관관계와 연관관계의 주인 (0) | 2021.09.11 |