One To One : 일대일 (1:1)
One To Many : 일대다 (1:N)
Many To One : 다대일 (N:1)
Many To Many : 다대다 (N:M)
@OneToOne어노테이션 : 다른 엔티티 객체를 필드로 정의했을 때, 일대일 연관관계로 매핑하기 위해 사용된다.
@JoinColumn어노테이션 : 매핑할 외래키를 설정한다.
EX) 상품에 하나의 상품정보만 매핑되는 구조
@Entity
@Table(name = "product_detail")
@Getter
@Setter
@NoArgsConstructor
@ToString(callSuper = true)
@EqualsAndHashCode(callSuper = true)
public class ProductDetail extends BaseEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String description;
@OneToOne //(optional=false) 예제 9.5
@JoinColumn(name = "product_number")
private Product product;
}
생성된 사품정보 엔티티 객체들 사용하기 위해, repository interface생성한다.
public interface ProductDetailRepository extends JpaRepository<ProductDetail, Long> {
}
product entity추가하기
EX)
@Entity
@Getter
@Setter
@NoArgsConstructor
@ToString(callSuper = true)
@EqualsAndHashCode(callSuper = true)
@Table(name = "product")
public class Product extends BaseEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long number;
@Column(nullable = false)
private String name;
@Column(nullable = false)
private Integer price;
@Column(nullable = false)
private Integer stock;
@OneToOne(mappedBy = "product") // 예제 9.6, 9.7
@ToString.Exclude // 예제 9.8
private ProductDetail productDetail;
한쪽의 테이블에서만 외래키를 바꿀 수 있도록 정하는 것이 좋다.
Entity는 양방향으로 매핑하되, 한쪽에게만 외래키를 줘야한다.
이때 사용되는 속성 값이 mappedBy이다
mappedBy는 어떡 객체가 주인인지 표시하는 속성이다.
mappedBy에 들어가는 값은 연관관계를 갖고 있는 상대 엔티티에 있는 연관관계 필드의 이름이다.
-> ProductDetail 엔티티가 Product엔티티의 주인이 된다.
양방향 연관관계 설정되면 ToString을 사용할 때, 순환참조가 발생한다.
순환참조 제거을 위해 exclude를 사용해 ToString에서 제외 설정을 하는 것이 좋다.
EX) mappedBy속성 추가한 Product엔티티 클래스
@Entity
@Getter
@Setter
@NoArgsConstructor
@ToString(callSuper = true)
@EqualsAndHashCode(callSuper = true)
@Table(name = "product")
public class Product extends BaseEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long number;
@Column(nullable = false)
private String name;
@Column(nullable = false)
private Integer price;
@Column(nullable = false)
private Integer stock;
@OneToOne(mappedBy = "product") // 예제 9.6, 9.7
@ToString.Exclude // 예제 9.8
private ProductDetail productDetail;
EX) 공급업체 인티티 클래스
@Entity
@Getter
@Setter
@NoArgsConstructor
@ToString(callSuper = true)
@EqualsAndHashCode(callSuper = true)
@Table(name = "provider")
public class Provider extends BaseEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
// 예제 9.14, 9.25, 9.27
@OneToMany(mappedBy = "provider", cascade = CascadeType.PERSIST, orphanRemoval = true)
@ToString.Exclude
private List<Product> productList = new ArrayList<>();
}
일반적으로 외래키를 갖는 쪽이 주인의 역할을 수행한다.
-> 상품 엔티티가 공급업체 엔티티의 주인이다.
EX) 상품 엔티티와 공급업체 엔티티의 다대일 연관관계 설정
@Entity
@Getter
@Setter
@NoArgsConstructor
@ToString(callSuper = true)
@EqualsAndHashCode(callSuper = true)
@Table(name = "product")
public class Product extends BaseEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long number;
@Column(nullable = false)
private String name;
@Column(nullable = false)
private Integer price;
@Column(nullable = false)
private Integer stock;
@OneToOne(mappedBy = "product") // 예제 9.6, 9.7
@ToString.Exclude // 예제 9.8
private ProductDetail productDetail;
// 예제 9.10
@ManyToOne
@JoinColumn(name = "provider_id")
@ToString.Exclude
private Provider provider;
// 예제 9.23
@ManyToMany
@ToString.Exclude
private List<Producer> producers = new ArrayList<>();
public void addProducer(Producer producer){
this.producers.add(producer);
}
}
이후 공급업체 엔티티를 활용할 수 있게 리포지토리 생성한다.
// 예제 9.11
public interface ProviderRepository extends JpaRepository<Provider, Long> {
}
일대다 연관관계의 겨이우, 여러 상품 엔티티가 포함될 수 있어
컬렉션(Collection, List, Map)형식으로 필드를 생성한다.
@OneToMany가 붙은 쪽에서 @JoinColumn어노테이션 사용하면, 상대 엔티티에 외래키가 설정된다.
ToString에서는 순환참조가 발생할 수 있어 제외처리를 하는것이 좋음
'fetch = FetchType.EAGER'로 설정한 것은 @OneToMany의 기본 fetch 전략이 Lazy이기 때문에 즉시로딩(Eager loading)으로 조정한다.
EX) 공급업체 엔티티와 상품 엔티티의 일대다 연관관계 설정
@Entity
@Getter
@Setter
@NoArgsConstructor
@ToString(callSuper = true)
@EqualsAndHashCode(callSuper = true)
@Table(name = "provider")
public class Provider extends BaseEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
// 예제 9.14, 9.25, 9.27
@OneToMany(mappedBy = "provider", cascade = CascadeType.PERSIST, orphanRemoval = true)
@ToString.Exclude
private List<Product> productList = new ArrayList<>();
}
상품 분류(category)테이블 생성되고, 상품 테이블에 외래키가 추가된다.
EX) 상품분류 엔티티 클래스
@Entity
@Getter
@Setter
@NoArgsConstructor
@ToString
@EqualsAndHashCode
@Table(name = "category")
public class Category {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String code;
private String name;
@OneToMany(fetch = FetchType.EAGER)
@JoinColumn(name = "category_id")
private List<Product> products = new ArrayList<>();
}
EX) CategoryRepository인터페이스
public interface CategoryRepository extends JpaRepository<Category, Long> {
}