본 포스팅의 이미지 저작권은 자바 ORM 표준 JPA 프로그래밍 - 기본편 (김영한) 강의에 있습니다.
연관관계가 필요한 이유
예제 시나리오
- 회원과 팀이 있다.
- 회원은 하나의 팀에만 속할 수 있다.
- 회원과 팀은 다대일 관계이다.
문제점 - 객체를 테이블에 맞추어 모델링한다.
객체는 따로 연관관계가 존재하지 않고, 테이블 연관관계를 따른다.
Member.java
@Entity public class Member {
@Id @GeneratedValue @Column(name = "MEMBER_ID")
private Long id;
@Column(name = "USERNAME")
private String name;
@Column(name = "TEAM_ID")
private Long teamId;
public Member() {}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Long getTeamId() {
return teamId;
}
public void setTeamId(Long teamId) {
this.teamId = teamId;
}
}
Team.java
@Entity public class Team {
@Id @GeneratedValue @Column(name = "TEAM_ID")
private Long id;
private String name;
public Team() {}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
시나리오
멤버와 팀을 저장하고, 저장된 멤버가 소속되어 있는 팀을 조회한다.
// 팀 저장
Team team = new Team();
team.setName("TeamA");
em.persist(team);
// 회원 저장
Member member = new Member();
member.setName("member1");
member.setTeamId(team.getId());
em.persist(member);
// 팀을 조회하기 위해서?
Member findMember = em.find(Member.class, member.getId());
Long findTeamId = findMember.getTeamId();
Team findTeam = em.find(Team.class, findTeamId);
tx.commit();
보다시피, 연관관계가 없기 때문에 객체간의 관계로 객체를 조회하는 것이 아닌, 테이블간의 관계로 객체를 조회하는 상황이 연출된다.
객체를 테이블에 맞추어 데이터 중심으로 모델링하면, 협력 관계를 만들 수 없다.
- 테이블은 외래 키로 조인을 사용해서 연관된 테이블을 찾는다.
- 객체는 참조를 이용하여 연관 된 객체를 찾는다.
- 테이블과 객체 사이에는 이러한 큰 간격이 있다.
단방향 연관관계
객체지향 모델링
앞서 보여준 테이블에 맞춘 모델링과 차이점은 Member 클래스에 teamId
와 같은 외래키를 갖는 것이 아닌, Team
객체 자체를 갖고 있다.
@Entity public class Member {
@Id @GeneratedValue @Column(name = "MEMBER_ID")
private Long id;
@Column(name = "USERNAME")
private String name;
@ManyToOne @JoinColumn(name = "TEAM_ID")
private Team team;
public Member() {}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Team getTeam() {
return team;
}
public void setTeam(Team team) {
this.team = team;
}
}
현재 Member와 Team이 N:1 관계이므로, @ManyToOne
애노테이션을 통해 연관관계를 매핑해준다.
조인 컬럼으로 어떠한 컬럼을 이용할 것인지를 지정하기 위해 @JoinColumn
애노테이션을 통해 TEAM_ID 컬럼을 조인 컬럼으로 지정한다.
테이블에 맞춘 모델링과는 다르게, Team과 TEAM_ID(외래키)를 연관관계 매핑한다.
// 팀 저장
Team team = new Team();
team.setName("TeamA");
em.persist(team);
// 회원 저장
Member member = new Member();
member.setTeam(team);
em.persist(member);
// 팀 조회
Member findMember = em.find(Member.class, member.getId());
Team findTeam = findMember.getTeam();
tx.commit();
조회 한 회원에서 findMember.getTeam()
메소드로 속한 팀을 바로 끄집어 낼 수 있다.
728x90
반응형