연관 관계 매핑 시, 연관관계의 주인을 객체 관계에서 어느 방향에 주어지느냐에 따라 어떻게 달라지는 지 알아봅시다 :)
연관관계의 주인이 N쪽에 있는 형태. 실무에서 가장 많이 쓰는 일반적인 형태라고 볼 수 있습니다.
연관관계 매핑 1편
이곳에 정리 해두었어요~
연관관계의 주인이 1쪽에 있는 형태.
코드 부터 보시죠
Member Entity
@Entity
public class Member {
@Id @GeneratedValue
@Column(name="member_id")
private Long id;
private String name;
}
Tema Entity
@Entity
public class Team {
@Id @GeneratedValue
@Column(name="team_id")
private Long id;
private String name;
@OneToMany
@JoinColumn(name="member_id")
private List<Member> members= new ArrayList<Member>();
}
코드에서 확인해 볼 수 있으듯이, Member Entity에는 자기 자신외엔 아무 연관관계의 정보가 없습니다.
Team Entity에는 일대다 관계로서 member_id 를 매핑하고 있습니다.
하지만! 문제가 있습니다. 외래 키의 주인은 DB설계상 Member 테이블입니다.
외래키의 주인이 Member테이블인 이유??
연관관계 매핑 1편
확인 해주세요~
외래키의 주인이 Member 테이블인 것이 왜 문제?? 객체를 persist하는 코드를 먼저 보시죠
//회원 저장
Member member-new Member();
...
em.persist(member);
// 팀 저장
Team team=new Team();
...
team.getMembers().add(member); //이 부분이 문제!
em.persist(team);
team.getMembers().add(member); 이 부분이 문제가 됩니다.
분명 외래 키의 주인은 Member 테이블입니다.
즉, 연관관계의 주인인 Team 객체는 반대편 테이블인 Member 테이블의 외래 키를 관리하게 되는 상황이죠.
위의 이유로 Team 객체가 INSERT문이 DB에서 나갈 때 마다 변경에 따라 Member 테이블의 외래 키도 수정되어야 하기 때문에 UPDATE문이 DB에 추가로 나가게 됩니다.
이는 성능의 문제를 일으킬 수 있습니다!!
Member Entity
@Entity
public class Member {
@Id @GeneratedValue
@Column(name="member_id")
private Long id;
private String name;
@ManyToOne
@JoinColum((insertable=false, updatable=false)
private Team team
}
Member Entity의 코드만 이런 식으로 바꿔주면 됩니다.
이러한 이유는 연관관계의 주인이 아닌 반대편 객체인 Member 에서 또 객체를 참조하는 것이기 때문입니다.
즉, 읽기 전용으로 해 놓지 않으면 DB에 SQL이 나가는 시점에 서로 외래 키를 참조할 것 입니다.
Member Entity
@Entity
public class Member {
@Id @GeneratedValue
@Column(name="member_id")
private Long id;
private String name;
@OneToOne
@JoinColumn(name="locker_id")
private Locker locker; //객체를 직접 참조
}
Locker Entity
@Entity
public class Locker {
@Id @GeneratedValue
@Column(name="locker_id")
private Long id;
private int location;
@OneToOne(mappedBy="locker")
private Member member; //객체를 직접 참조
}
대상 테이블에 외래 키를 갖고 있기 때문에 주 객체인 Member 객체를 조회해도 대상 객체인 Locker 객체를 조회하지 못합니다.
따라서 DB에 주 테이블인 Member테이블의 PK값을 가지고 대상 테이블인 Locker 테이블의 외래 키와 같은 지 확인 해 보는 작업이 추가로 필요하게 됩니다.
즉, 이와 같은 코드를 짭시다!
Order Entity
@Entity
@Table(name="orders")
public class Order{
@Id @GeneratedValue
@Column(name="order_id")
private Long id;
@oneToMany(mappedBy="order")
private List<OrderItem> orderItems=new ArrayList<OrderItem>();
private LocalDateTime orderDate;
}
Item Entity
@Entity
public class Item{
@Id @GeneratedValue
@Column(name="item_id")
private Long id;
@oneToMany(mappedBy="item")
private List<OrderItem> orderItems=new ArrayList<OrderItem>();
private String name;
private int price;
}
OrderItem Entity
@Entity
public class OrderItem{
@Id @GeneratedValue
@Column(name="orderitem_id")
private Long id;
@ManyToOne
@JoinColumn(name="order_id")
private Order order;
@ManyToOne
@JoinColumn(name="item_id")
private Item item;
private int orderPirce;
private int quantity;
}
이런 식으로 연결 테이블을 놓으면 되게 됩니다!
이 글은 인프런 김영한님의 '자바 ORM 표준 JPA 프로그래밍 - 기본편'을 수강하고 작성합니다.
출처:https://www.inflearn.com/course/ORM-JPA-Basic
잘 보고 갑니다 ~~!