@ManyToOne - 다대일 ( N : 1)
연관관계 매핑 시 가장 많이 사용하는 매핑 방법이다.
다대일은 외래키(FK)를 갖고 있는 "다"쪽이 연관관계의 주인이 된다.
단방향 매핑
@Entity
public class Member {
@Id @GeneratedValue
@Column(name = "MEMBER_ID")
private Long id;
private String username;
@ManyToOne
@JoinColumn(name = "TEAM_ID")
private Team team;
...
}
@Entity
public class Team {
@Id @GeneratedValue
@Column(name = "TEAM_ID")
private Long id;
private String name;
...
}
@JoinColumn을 어노테이션을 통해 참조할 객체의 왜래키(FK)의 이름을 지정한다.
양방향 매핑
단방향 일 경우 Team 엔티티에서는 Member 엔티티의 필드 값을 조회할 수 없다.
Team 엔티티에서도 Member 엔티티의 필드 값을 조회해야 한다면
아래처럼 Team 엔티티에서 mappedBy로 연관관계 매핑 주인을 지정해줘야한다.
public class Team {
@Id @GeneratedValue
private Long id;
private String name;
@OneToMany(mappedBy = "team")
private List<Member> member;
...
}
연관관계 매핑 주인에 대한 자세한 설명은 아래의 링크를 참조하자.
@OneToMany - 일대다 ( 1 : N )
객체와 테이블의 차이 때문에 반대편 테이블의 외래 키를 관리하는 특이한 구조다.
다대일의 반대로, 일대다는 "일"이 연관관계의 주인이 되고, "다" 쪽에 외래키(FK)가 있다.
@Entity
public class Member {
@Id
@GeneratedValue
@Column(name = "MEMBER_ID")
private Long id;
@Column(name = "USERNAME")
private String username;
...
}
public class Team {
@Id @GeneratedValue
private Long id;
private String name;
@OneToMany(mappedBy = "team")
@JoinColumn(name = "TEAM_ID")
private List<Member> member;
...
}
일대다 매핑 방식의 단점
- 엔티티가 관리하는 외래 키가 다른 테이블에 있다. (구조가 비정상적)
- 연관관계 관리를 위해 추가로 UPDATE 쿼리를 실행한다
그러므로 진짜 꼭 사용해야 하는 것이 아니라면, 일대다 단항향 매핑보다는 "다대일 양방향 매핑"을 사용하는 것이 좋다.
@OneToOne - 일대일 ( 1 : 1 )
일대일은 반대도 일대일이다.
그렇기 때문에 주 테이블이나 대상 테이블 중에 외래키(FK)를 상황에 맞게 선택하여 두면된다.
주 테이블에 외래키를 둘 경우 | 대상 테이블에 외래 키를 둘 경우 | |
특징 | 주 객체가 대상 객체의 참조를 가지는 것 처럼 주 테이블에 외래 키를 두고 대상 테이블을 찾는다. |
대상 테이블에 외래 키가 존재 |
장점 | 주 테이블만 조회해도 대상 테이블에 데이터가 있는지 확인 가능 |
주 테이블과 대상 테이블을 일대일에서 일대다 관계로 변경할 때 테이블 구조 유지 |
단점 | 값이 없으면 외래 키에 null 허용 | 프록시 기능의 한계로 지연 로딩으로 설정해도 항상 즉시 로딩된다. |
매핑 방식은 다대일과 똑같다. @ManyToOne 대신 @OneToOne을 달아주면 된다.
단방향 매핑
@Entity
public class Member {
@Id @GeneratedValue
@Column(name = "MEMBER_ID")
private Long id;
private String username;
@OneToOne
@JoinColumn(name = "TEAM_ID")
private Team team;
...
}
@Entity
public class Team {
@Id @GeneratedValue
@Column(name = "TEAM_ID")
private Long id;
private String name;
...
}
양방향 매핑
다대일 양방향 매핑 처럼 외래키가 있는 곳이 연관관계 주인이 된다.
동일하게 반대편은 mappedBy를 적용해주면 된다.
@Entity
public class Team {
@Id @GeneratedValue
@Column(name = "TEAM_ID")
private Long id;
private String name;
@OneToOne(mappedBy = "team")
private Member member;
...
}
@ManyToMany - 다대다 ( N : N )
관계형 데이터베이스는 정규화된 테이블 2개로 다대다 관계를 표현할 수 없다.
아래 처럼 연결 테이블을 추가해서 일대다 또는 다대일 관계로 풀어내야 한다.
이전과 다른 특징으로는 연결 테이블용 엔티티 추가하고 @JoinTable로 연결 테이블을 지정한다.
@Entity
public class MemberTeam {
@Id @GeneratedValue
private Long id;
@ManyToOne
@JoinColumn(name = "MEMBER_ID")
private Member member;
@ManyToOne
@JoinColumn(name = "TEAM_ID")
private Team team;
...
}
그 다음 Member와 Team을 연결 테이블에 대해 @OneToMany 일대다 연관관계로 매핑하면 다대다 연관관계가 된다.
@Entity
public class Member {
@Id @GeneratedValue
private Long id;
private String name;
@OneToMany(mappedBy = "member")
private List<MemberTeam> teams;
...
}
@Entity
public class Team {
@Id @GeneratedValue
private Long id;
private String name;
@OneToMany(mappedBy = "team")
private List<MemberTeam> members;
...
}
다대다 사용은 자재하는 것이 좋다.
다대다 매핑은 실무에서 사용하지 않는다고 한다. 그 이유는 다음과 같다.
- 연결 테이블이 단순히 연결만 하고 끝나지 않는다.
- 중간 테이블에는 매핑정보만 들어가고 추가 데이터를 넣는 것이 불가능하다.
- 중간 테이블이 숨겨져 있기 때문에 쿼리가 예상하지 못하는 형태로 나간다.
- 실무 비즈니스는 복잡해서 ManyToMany로 풀 수있는게 거의 없다.
📌 추가로 알아볼 내용
'◼ JAVA > JPA' 카테고리의 다른 글
[JPA] 영속성 전이(cascade)와 고아객체(orphalRemoval)란? (0) | 2023.06.07 |
---|---|
[JPA] 상속관계 매핑, 매핑 정보 상속에 대해 알아보자. (0) | 2023.06.07 |
[JPA] 연관관계 매핑 주인에 대해서 (mappedBy) (0) | 2023.06.06 |
[JPA] 기본 키 매핑 (기본키 자동 생성 전략) (0) | 2023.06.05 |
[JPA] 엔티티 매핑 어노테이션과 속성 값 정리 (0) | 2023.06.05 |