@ManyToOne
@OneToMany
@OneToOne
@ManyToMany
테이블
외래키 하나로 양쪽 조인 가능. 사실 방향이라는 개념이 없다.
객체
참조용 필드가 있는 쪽으로만 참조 가능. 한쪽만 참조하면 단방향, 양쪽이 서로 참조하면 양방향
mappedBy
)@Entity
public class Member {
@Id @GeneratedValue
@Column(name = "MEMBER_ID")
private Long id;
private String username;
@ManyToOne
@JoinColumn(name = "TEAM_ID") // 외래키(TEAM_ID)와 team 필드를 매핑
private Team team;
// Getter, Setter
...
}
@Entity
public class Team {
@Id @GeneratedValue
@Column(name = "TEAM_ID")
private Long id;
private String name;
// Getter, Setter
...
}
회원은 Member.team
으로 팀 엔티티를 참조할 수 있지만, 팀에는 회원을 참조하는 필드가 없다.
@Entity
public class Member {
@Id @GeneratedValue
@Column(name = "MEMBER_ID")
private Long id;
private String username;
@ManyToOne
@JoinColumn(name = "TEAM_ID") // 외래키(TEAM_ID)와 team 필드를 매핑
private Team team;
public void setTeam(Team team) {
this.team = team;
if (!team.getMembers().contains(this)) { // 무한루프에 빠지지 않도록 체크
team.getMembers().add(this);
}
}
// Getter, Setter
...
}
@Entity
public class Team {
@Id @GeneratedValue
@Column(name = "TEAM_ID")
private Long id;
private String name;
@OneToMany(mappedBy = "team")
private List<Member> members = new ArrayList<>();
public void addMember(Member member) {
this.members.add(member);
if (member.getTeam() != this) { // 무한루프에 빠지지 않도록 체크
member.setTeam(this);
}
}
// Getter, Setter
...
}
연관관계 편의 메소드(setTeam()
, addMember()
)를 작성해서 항상 서로 참조하게 만들어 둔다.
보통 편의 메소드는 한 곳에만 작성하는데, 양쪽에 다 작성하면 무한루프에 빠지므로 주의해야 한다.
위 처럼 무한루프에 빠지지 않도록 검증 로직을 작성하고, 사용 시 둘 중 하나만 호출해서 사용하도록 하자.
일(1)이 연관관계의 주인이다. 권장하는 방법도 아니고 실무에서도 거의 사용되지 않는다고 한다.
권장하지 않는 이유는
@JoinColumn
을 꼭 사용해야하고, 그렇지 않다면 조인 테이블 방식을 사용해야 한다.(중간에 테이블을 하나 추가)일대다 단방향 매핑보다는 다대일 양방향 매핑을 사용하자.
// 참고: JPA - One To Many 단방향의 문제점
이런 매핑은 공식적으로 존재하지 않는다. 대신 다대일 양방향 매핑을 사용해야 한다.
public class Team {
...
@OneToMany
@JoinColumn(name="TEAM_ID")
private List<Member> members = new ArrayList<>();
...
}
public class Member {
...
@ManyToOne
@JoinColumn(name="TEAM_ID", insertable=false, updatable=false)
private Team team;
...
}
@JoinColumn(insertable=false, updatable=false)
: 다대일 쪽은 읽기만 가능하게 설정// 더 알아보기: @ManyToOne 에는 왜 mappedBy 속성이 없을까요?
// 주 테이블에 외래키 단방향
@ManyToOne
) 단방향 매핑과 유사mappedBy
를 넣어준다.// 일대일에선 대상 테이블에 외래키를 두기보단 이 방식이 차라리 나음
// 대상 테이블에 외래키 양방향
// 대상 테이블에 외래키 단방향 관계는 JPA 지원 x, 양방향 관계는 지원 o
실전에선 절대 쓰면 안되는 구조이다.
관계형 데이터베이스는 정규화된 테이블 2개로 다대다 관계를 표현할 수 없다.
중간에 연결 테이블을 추가해서 일대다, 다대일 관계로 풀어내야 한다.
반면 객체는 컬렉션을 사용해서 객체 2개로 다대다 관계가 가능하다.
@ManyToMany
를 사용한다.JoinTable
로 연결 테이블을 지정한다.@ManyToMany
사용 불가함. 주문, 상품 엔티티에는 추가한 컬럼들을 매핑할 수 없음.)@ManyToMany
-> @OneToMany
+ @ManyToOne
로 풀어서 연결 테이블을 매핑하자.ORDER_ID
)를 선언해서 사용하는게 복합키 PK 선언보다 조금 더 선호됨.