🧡 연관관계 매핑 종류와 방향
단방향과 양방향
- 단방향 : 두 엔티티의 관계에서 한 쪽의 엔티티만 참조하는 형식
- 양방향 : 두 엔티티의 관계에서 각 엔티티가 서로의 엔티티를 참조하는 형식
외래키를 가진 테이블이 관계의 주인이 되며, 주인은 외래키를 사용할 수 있으나 상대 엔티티는 읽는 작업만 수행할 수 있다.
상품정보 -> 상품
@Entity
public class ProductDetail {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String description;
@OneToOne
@JoinColumn(name = "product_number")
private Product product;
}
public @interface OneToOne {
...
FetchType[] cascade() default EAGER;
...
boolean optional() default true;
...
}
EAGER
(즉시 로딩 전략) 채택optional()
메서드는 기본값 true
객체에서의 양방향은 양쪽에서 단방향으로 서로 매핑하는 것을 의미한다. 따라서
상품정보 <-> 상품
@Entity
public class Product {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long number;
private String name;
private Integer price;
private Integer stock;
@OneToOne
private ProductDetail productDetail;
그러나 양방향 매핑을 단방향 두번을 걸쳐 진행하면 left outer join이 두 번이나 수행되어 효율성이 떨어진다.
@ToString.Exclude
를 통해 ToString을 제외한다.@Entity
public class Product {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long number;
private String name;
private Integer price;
private Integer stock;
@OneToOne(mappedBy = "product")
private ProductDetail productDetail;
ProductDetail(주인) <-> Product
공급업체에 여러개의 상품이 납품되는 상황.
상품 테이블(N) <-> 공급업체(1)
💚 다대일 단방향 매핑
상품(N) -> 공급업체(1)
// 공급업체
@Entity
public class Provider {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
}
// 상품
@Entity
public class Product {
...
@OneToOne(mappedBy = "product")
@ToString.Exclude
private ProductDetail productDetail
@ManyToOne
@JoinColumn(name = "provider_id")
@ToString.Exclude
private Provider provider;
}
💙 다대일 양방향 매핑
상품(N) <-> 공급업체(1)
// 공급업체
@Entity
public class Provider {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
@OneToMany(mappedBy = "provider", fetch = FetchType.EAGER)
@ToString.Exclude
private List<Product> productList = new ArrayList<>();
}
공급업체당 여러 상품이 포함될 수 있어 컬렉션 형식인 List를 사용한다.
💜 일대다 단방향 매핑
상품(N) -> 상품 분류(1)
@Entity
public class Category {
...
@OneToMany(fetch = FetchType.EAGER)
@JoinColumn(name = "category_id")
private List<Product> products = new ArrayList<>();
}
위 상태에서 실행하면 상품 테이블의 id에 외래키가 추가된다.
💘@JoinColumn
다대일 상황에서는name
을 지정해주거나 원하는 컬럼을 지정하는referencedColumnName
을 사용하지 않는 이상 생략하더라도 매핑에 문제가 없다. 하지만 일대일, 일대다 단방향 매핑에서 생략하게 되면 중간 테이블로 Join 테이블이 생성되는 전략이 자동으로 채택된다.