객체지향스럽게 어떻게 설계하는지
제일 어려운 내용
객체가 지향하는 패러다임 vs 데이터가 지향하는 패러다임
목표
객체와 테이블 연관관계의 차이를 이해
객체의 참조와 테이블의 외래 키를 매핑
방항 (Direction) : 단방향, 양방향
다중성 (Multiplicity) : 다대일, 일대다, 일대일, 다대다
연관관계의 주인(Owner) : 객체 양방향 연관관계는 관리가 필요
- 연관관계가 필요한 이유
‘객체지향 설계의 목표는 자율적인 객체들의 협력 공동체를 만드는 것이다.’
객체를 테이블에 맞추어 데이터 중심으로 모델링하면 협력 관계를 만들 수 없다
- 테이블은 외래 키로 조인을 사용해서 연관된 테이블을 찾는다.
- 객체는 참조를 사용해서 연관된 객체를 찾는다
- 단방향 연관관계
/**
* Created by eunbi on 2021. 9. 21.
*/
@Getter
@Setter
@Entity
public class Member {
@Id
@GeneratedValue
private Long id;
@Column(name = "USER_NAME")
private String name;
// @Column(name = "TEAM_ID")
// private Long teamId;
@ManyToOne
@JoinColumn(name= "TEAM_ID")
private Team team;
}
@Getter
@Setter
@Entity
public class Team {
@Id @GeneratedValue
@Column(name = "TEAM_ID")
private Long id;
@Column(name = "TEAM_NAME")
private String name;
}
Team team = new Team();
team.setName("team1");
em.persist(team);
Member member = new Member();
member.setName("mem1");
// member.setTeamId(team.getId());
em.persist(member);
// Member 내부에서 join 하여 Team을 이용할 수 있다.
Member findMember = em.find(Member.class, member.getId());
Team findTeam = findMember.getTeam();
// 쿼리 호출을 위한 영속성 초기화
em.flush();
em.clear();
fetchType : LAZY,
*양방향 연관관계
테이블 연관관계는 바뀌는 것이 없다.
하지만 객체 상에서는 서로를 참조한다.
객체의 연관관계 : 2개 (각자 참조로 인한 연관관계)
- 회원 -> 팀 연관관계 (단뱡향)
- 팀 -> 회원 연관관계 (단방향)
테이블 연관관계 : 1개 (외래키로 연관관계 종결)
- 회원 <-> 팀 연관관계 (양방향)
객체의 양방향 관계는 서로다른 단방향 관계 2개다
연관관계의주인 : 양방향 매핑에서 서로의 참조로 어느 값을 업데이트 할 지 딜레마가 일어난다.
-> 객체 둘 중 하나로 외래키를 관리해야 한다.
양방향 매핑 규칙
- 객체의 두 관계중 하나를 연관관계의 주인으로 지정
- 연관관계의 주인만이 외래 키를 관리(등록, 수정)
- 주인이 아닌쪽은 조회만 가능
- 주인은 MappedBy 속성 사용불가
- 주인이 아닌쪽은 MappedBy 속성으로 주인 지정
주인 지정 원칙
- 외래 키가 있는 곳이 주인
- 다대일 중 다 쪽이 주인
양방향 매핑 시 가장 많이 하는 실수 : 연관관계의 주인에 값을 입력하지 않음
@Entity
public class Team {
@Id @GeneratedValue
@Column(name = "TEAM_ID")
private Long id;
@Column(name = "TEAM_NAME")
private String name;
@OneToMany(mappedBy = "team”)// 2-2. 양방향 매핑
private List<Member> memberList = new ArrayList<>();
}
// 2-2. 양방향 매핑
// Member와 같은 팀 소속인 Member들 찾기
Member findMember2 = em.find(Member.class, member.getId());
List<Member> memberList = findMember2.getTeam().getMemberList();