[JPA] 엔티티 연관관계
- 방향 : 단방향, 양방향이 존재한다.
- JPA에는 단방향만 존재하며 양방향의 경우 단방향이 양쪽에서 이루어진다
- DB에서는 양방향만 존재한다
- 다중성 : 다대일(N:1), 일대다(1:N), 일대일(1:1), 다대다(N:N)
다대일(N:1), 일대다(1:N)
(1) 단뱡향 연관관계
- 한 멤버는 한 팀에 속하고 한 팀에는 여러 멤버가 속한다 (Member N : Team 1)
@Entity
public class Team {
@Id
private String id;
private String name;
}
@Entity
public class Member {
@Id
private String id;
private String username;
@ManyToOne
@JoinColumn(name="team_id")
private Team team;
}
-
Member
→Team
은 접근이 가능하다 (member.getTeam()
) -
Team
→Member
는 접근 불가능하다
(2) 양방향 연관관계
- 기존 단방향의 연관관계를
Team
→Member
접근도 가능하게 해보자
@Entity
public class Member {
@Id
private String id;
private String username;
@ManyToOne
@JoinColumn(name="team_id")
private Team team;
}
@Entity
public class Team {
@Id
private String id;
private String name;
@OneToMany(mappedBy = "team", cascade = CascadeType.ALL)
private List<Member> members = new ArrayList<Member>();
}
- Team : Member = 1 : N 관계 이기 때문에
List
를 사용한다 - mappedBy 속성
- 객체 연관관계에는 양방향이 존재하지 않기 때문에 단방향 2개로 양방향처럼 만들어야 한다.
- 실제 DB는 외래키 하나로 양방향 관계를 맺는다. 두개의 연관관계 중 하나를 정해서 테이블의 외래키를 관리하는 주인을 설정해야 한다
- 주인은 외래키를 관리(등록, 수정, 삭제) 할 수 있고 주인이 아닌 쪽은 읽기만 가능
-
mappedBy
를 설정하지 않은 쪽이 주인이다 - 정확히 정리하자면
@ManyToOne
은 외래키를 갖고(주인)이고@OneToMany
는 외래키를 갖지 않는다
- cascade 속성
- 영속성 전이 속성으로 부모 엔티티에게 수행된 작업이 자식 엔티티에도 전파된다
- 여기서는 Team에서 cascade가 걸려있기 때문에 Team이 지워지면 속한 Member들이 같이 지워지게 된다.
일대일(1:1)
- 일대다, 다대일은 항상 다(N)쪽이 외래키를 갖지만 일대일은 양쪽 중 어느 곳이나 외래키를 갖을 수 잇다
- 양쪽 중 어느 쪽에나 외래키를 갖을 수 있지만, 주인이 정해져야 한다.
- 많이 사용되는 쪽을 주인으로 설정한다
(1) 단방향 연관관계
@Entity
public class Member {
@Id
private String id;
private String username;
@OneToOne
@JoinColumn(name="locker_id")
private Locker locker;
}
@Entity
public class Locker {
@Id
private String id;
private String name;
}
(2) 양방향 연관관계
@Entity
public class Member {
@Id
private String id;
private String username;
@OneToOne
@JoinColumn(name="locker_id")
private Locker locker;
}
@Entity
public class Locker {
@Id
private String id;
private String name;
@OneToOne(mappedBy="locker")
private Member member;
}
다대다(N:N)
- DB에서 다대다 관계는 연결 테이블이 필요하다
-
실무에서 사용하면 안된다
- 이유 :
@ManyToMany
로 생성된 연결 테이블은 변경이 불가능해서 유연하지 못하다 - 다대다(N:N)를 다대일(N:1)과 일대다(1:N)로 나누어 표현한다
- 연결 테이블을 Entity로 직접 만든다
- 이유 :
(1) 단방향 연관관계
@Entity
public class Member {
@Id
private String id;
private String username;
@ManyToMany
@JoinTable(name="member_product",
joinColumns=@JoinColumn(name="member_id"),
inverseJoinColumns=@JoinColumn(name="product_id"))
private List<Product> products = new ArrayList<Product>();
}
@Entity
public class Product {
@Id
private String id;
private String name;
}
(2) 양방향 연관관계
@Entity
public class Member {
@Id
private String id;
private String username;
@ManyToMany
@JoinTable(name="member_product",
joinColumns=@JoinColumn(name="member_id"),
inverseJoinColumns=@JoinColumn(name="product_id"))
private List<Product> products = new ArrayList<Product>();
}
@Entity
public class Product {
@Id
private String id;
private String name;
@ManyToMany(mappedBy="products")
private List<Member> members;
}