객체과 테이블 연관관계 차이를 이해를 해야한다.
객체는 참조를 통해 접근한다면 테이블은 FK 외래키를 통해 연관관계를 가진다.
그래서 JPA 연관관계 매핑 글에서는 객체의 참조와 테이블의 외래키를 어떻게 매칭해야하는 것인가에 대해서 정리할 생각이다.
@Entity
public class Member {
@Id @GeneratedValue
private Long id;
private String name;
@Column(name="crew_Id")
private Long crewId;
...
}
@Entity
public class Crew {
@Id @GeneratedValue
private Long id; //crewId
private String name;
...
}
Crew crew = new Crew("crew1");
em.persist(crew);
Member member = new Member("member1");
member.setCrewId(crew.getId()); // 이 부분
em.persist(member);
Member findMember = em.find(Member.class, member.getId());
Long crewId = findMember.getCrewId();
Crew findCrew = em.find(Crew.class, crewId);
그래서 이처럼 객체를 테이블에 맞추어 모델링을 하면 객체 간의 협력 관계를 만들 수 없다.
객체는 참조를 통해서 연관된 객체를 찾고, 테이블은 FK를 사용해서 연관된 테이블을 찾는다는 큰 간격이 있다.
우선 이러한 차이가 있다는 것을 알고있자.
이제 객체지향스럽게 모델링을 해보자.
@Entity
public class Crew {
@Id @GeneratedValue
private Long id; //crewId
private String name;
...
}
@Entity
public class Member {
@Id @GeneratedValue
private Long id;
private String name;
@ManyToOne // Member 입장에서 Crew를 보면 Member:Crew=N:1
@JoinColumn(name="crew_id") // 이 연관관계에서 join할 컬럼은 뭐야?를 의미함.
private Crew crew;
...
}
Crew crew = new Crew("crew1");
em.persist(crew);
Member member = new Member("member1");
member.setCrew(crew); // 이 부분
em.persist(member);
Member findMember = em.find(Member.class, member.getId());
Crew findCrew = findMember.getCrew(); // 이 부분
@Entity
public class Member {
@Id @GeneratedValue
private Long id;
private String name;
@ManyToOne
@JoinColumn(name="crew_id")
private Crew crew;
...
}
@Entity
public class Crew {
@Id @GeneratedValue
private Long id; //crewId
private String name;
@OneToMany(mappedBy="crew") // Crew입장에서 Member는 1:N
private List<Member> members = new ArrayList<>();
...
}
Member findMember = em.find(Member.class, member.getId());
Crew findCrew = findMember.getCrew(); // 이 부분
// 양방향
List<Member> members = findCrew.getMembers();
이제 mappedBy에 대해서 조금 더 자세히 알아보자.
@Entity
public class Member {
@Id @GeneratedValue
private Long id;
private String name;
@ManyToOne
@JoinColumn(name="crew_id")
private Crew crew;
...
}
@Entity
public class Crew {
@Id @GeneratedValue
private Long id; //crewId
private String name;
@OneToMany(mappedBy="crew") // Crew입장에서 Member는 1:N
private List<Member> members = new ArrayList<>();
...
}
[예시] - 단순하게 작성함.
@Entity
public class Member {
@Id @GeneratedValue
private Long id;
private String name;
@ManyToOne
@JoinColumn(name="crew_id")
private Crew crew;
public void setCrew(Crew crew){
this.crew = crew;
crew.getMembers().add(this); // 이 부분
}
...
}
연관관계를 매핑시 고려사향으로는 다대다인지, 다대일인지 등과 같은 다중성과 단방향인지 양방향인지, 연관관계의 주인은 누구로 정할건지 등을 고려해야한다.
[다대일 단방향 코드]
@Entity
public class Crew {
@Id @GeneratedValue
private Long id; //crewId
private String name;
...
}
@Entity
public class Member {
@Id @GeneratedValue
private Long id;
private String name;
@ManyToOne // Member 입장에서 Crew를 보면 Member:Crew=N:1
@JoinColumn(name="crew_id") // 이 연관관계에서 join할 컬럼은 뭐야?를 의미함.
private Crew crew;
...
}
[일대다 단방향]
@Entity
public class Crew {
@Id @GeneratedValue
private Long id; //crewId
private String name;
@OneToMany
@JoinColumn(name="crew_id")
private List<Member> members = new ArrayList<>();
...
}
@Entity
public class Member {
@Id @GeneratedValue
private Long id;
private String name;
...
}
[일대일 단방향 - 주테이블에 외래키가 있는 경우]
@Entity
public class Member {
@Id @GeneratedValue
private Long id;
@OneToOne
@JoinColumn(name="locker_id")
private Locker locker;
}
@Entity
public class Locker {
@Id @GeneratedValue
private Long id;
private String name;
// 양방향으로 하고싶다면 다음과 같은 코드 추가
@OneToOne(mappedBy="locker")
private Member member;
}
자바 ORM 표준 JPA 프로그래밍-기본편을 학습하면서 정리한 블로그입니다.