일대일 관계
- 일대일 관계는 반대도 일대일이다.
- 주 테이블이나 대상 테이블 중에 외래 키 선택 가능
- 주 테이블에 왜래 키
- 대상 테이블에 외래 키
- 외래 키에 DB 유니크(UNI) 제약조건 추가
다대일(@ManyToOne) 단방향 매핑과 유사하다.
Locker를 만들어주자.
package hellojpa;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
public class Locker {
@Id @GeneratedValue
private Long id;
private String name;
}
Member Class에도 설정을 해주고 돌리면 Locker_ID와 Member Class가 생성이 된다.
@OneToOne
@JoinColumn(name = "LOCKER_ID")
private Locker locker;
Hibernate:
create table Locker (
id bigint not null,
name varchar(255),
primary key (id)
)
Hibernate:
create table Team_Member (
Team_TEAM_ID bigint not null,
members_MEMBER_ID bigint not null
)
Locker class에도 걸어주자.
@OneToOne(mappedBy = "locker")
private Member member;
일대일 관계인데 대상 테이블에 외래 키 단방향을 보면
- 대상 테이블에서의 단방향 관계는 JPA에서 지원하지 않는다.
- 양방향 관계는 지원해줌
일대일: 대상 테이블에 외래 키 양방향은
- 일대일 주 테이블에 외래 키 양방향과 매핑 방법은 같다.
MEMBER 테이블에 Locker을 넣고 값이 있으면 돌고 없으면 안돌게 해줄 수 있다. 명확한 1:1 관계이면 이러한 그림이 적절하다.
일대일을 정리해보자.
주 테이블에 외래 키
- 주 객체가 대상 객체의 참조를 가지는 것 처럼
- 객체지향 개발자 선호
- JPA 매핑 관리
- 장점: 주 테이블만 조회해도 대상 테이블에 데이터가 있는지 확인이 가능하다.
- 단점: 값이 없으면 외래 키에 null 허용
대상 테이블에 외래 키
- 대상 테이블에 외래 키가 존재
- 전통적인 DB 개발자가 선호
- 장점: 주 테이블과 대상 테이블을 일대일에서 일대다 관계로 변경할 때 테이블 구조 유지
- 단점: 프록시 기능의 한계로 지연 로딩으로 설정해도 항상 즉시 로딩(프록시는 뒤에서 설명)
이제 다대다 N:M을 보자. 별로 안중요하고 실무에서 쓰면 안되는 방법이다.
- 관계형 DB는 정규화된 테이블 2개로 다대다 관계를 표현할 수 없다.
- 연결 테이블을 추가해 일대다, 다대일 관계로 풀어내야 한다.
객체도 마찬가지로 컬렉션을 사용해서 객체 2개로 다대다 관계가 가능하다.
- @ManyToMany로 사용가능 하고
- @JoinTable로 연결 테이블 지정
- 다대다 매핑: 단방향, 양방향 가능
Product Class를 하나 만들어주자.
package hellojpa;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
@Entity
public class Product {
@Id @GeneratedValue
private Long id;
private String name;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Member class에 아래와 같이 넣어준다.
@ManyToMany
@JoinTable(name = "MEMBER_PRODUCT")
private List<Product> products = new ArrayList<>();
MEMBER_PRODUCT 테이블이 생기고 MEMBER_PRODUCT 제약조건이 생기게 된다.
create table MEMBER_PRODUCT (
Member_MEMBER_ID bigint not null,
products_id bigint not null
)
Hibernate:
alter table MEMBER_PRODUCT
add constraint FKc6hsxwm11n18ahnh5yvbj62cf
foreign key (products_id)
references Product
Hibernate:
alter table MEMBER_PRODUCT
add constraint FK4ibylolqmostllrjdc147aowv
foreign key (Member_MEMBER_ID)
references Member
단방향인데 양방향 만들고 싶으면 product에서 아래와 같이 설정해준다.
@Entity
public class Product {
@Id @GeneratedValue
private Long id;
private String name;
@ManyToMany(mappedBy = "products")
private List<Member> members = new ArrayList<>();
다대다 매핑의 한계를 보자.
- 편리해 보이지만 실무에서 사용하면 안된다.
- 연결 테이블이 단순히 연결만 하고 끝나지 않고
- 주문시간, 수량 같은 데이터가 들어올 수 있다.
다대다 한계를 해결해주는 방법이 있다.
- 연결 테이블용 엔티티 추가(연결 테이블을 엔티티로 승격)
- @ManyToMany -> @OneToMany, @ManyToOne
MemberProduct를 아래와 같이 설정해주자. pk 하나만 잡고 가면 JPA mapping이 심플해진다.
package hellojpa;
import javax.persistence.*;
import java.time.LocalDateTime;
@Entity
public class MemberProduct {
@Id
@GeneratedValue
private Long id;
@ManyToOne
@JoinColumn(name = "MEMBER_ID")
private Member member;
@ManyToOne
@JoinColumn(name = "PRODUCT_ID")
private Product product;
private int count;
private int price;
private LocalDateTime orderDateTime;
}
Member에서는 MemberProduct를 이렇게 넣어주면 된다.
@Entity
public class Member {
@Id @GeneratedValue
@Column(name = "MEMBER_ID")
private Long id;
@Column(name = "USERNAME")
private String username;
@ManyToOne
@JoinColumn(name = "TEAM_ID", insertable = false, updatable = false)
private Team team;
@OneToOne
@JoinColumn(name = "LOCKER_ID")
private Locker locker;
@OneToMany(mappedBy = "member")
private List<MemberProduct> memberProducts = new ArrayList<>();
<출처 김영한: 자바 ORM 표준 JPA 프로그래밍 - 기본편 >
https://www.inflearn.com/course/ORM-JPA-Basic/dashboard
'Spring > JPA' 카테고리의 다른 글
고급매핑 - 상속관계 매핑 (0) | 2022.05.27 |
---|---|
실전 예제 3 - 다양한 연관관계 매핑 (0) | 2022.05.25 |
다대일 N:1 / 일대다 1:N (0) | 2022.05.25 |
예제 - 연관관계 매핑 시작 (0) | 2022.05.25 |
양방향 연관관계와 연관관계의 주인 (0) | 2022.05.08 |