์ด๋ฐ์์ผ๋ก ๊ตฌ์ฑ๋ ๊ตฌ์กฐ๋ฅผ ์๊ฐํ๋ฉฐ ํ๋ก์ ํธ ์ฝ๋ ๋จ์ ๊ตฌํํด๋ณด๋๋ก ํ๊ฒ ๋ค.
1. ์ต์ ๊ด๋ จ DB ํ ์ด๋ธ์ ํด๋น๋๋ ์ํฐํฐ
1๏ธโฃ ์ต์ ์นดํ ๊ณ ๋ฆฌ ์ํฐํฐ
์ฐ์ ์ต์ ์นดํ ๊ณ ๋ฆฌ๋ถํฐ ์กด์ฌํด์ผํ๋ค.
@Entity
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class OptionCategory extends BaseEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "option_category_id")
private Long id;
private String name;
@OneToMany(mappedBy = "optionCategory")
private List<Option> options = new ArrayList<>();
@Builder
private OptionCategory(String name) {
this.name = name;
}
public void addOptions(Option option){
options.add(option);
}
}
์ต์ ์นดํ ๊ณ ๋ฆฌ : ์ต์ = 1:N ๊ด๊ณ์ด๋ฏ๋ก @OneToMany๋ฅผ ํตํด ๊ด๊ณ๋ฅผ ์ฐ๊ฒฐํด์ค๋ค.
@NoArgsConstructor(access = AccessLevel.PROTECTED) ๋ฅผ ํตํด ๊ธฐ๋ณธ ์์ฑ์๋ฅผ ์์ฑํด์ฃผ๊ณ , AccessLevel์ ์ ํด์ฃผ๋ฉด์ IDE์์ ํ๋ฒ๋ ๊ธฐ๋ณธ ์์ฑ์์ ์ค๋ฅ๋ฅผ ์ฒดํฌํด์ค๋ค.
์์ ์์ฑ์ ํ๋ผ๋ฏธํฐ๋ฅผ ๋ชฐ๋ผ๋ ๋ณ์ ์ด๋ฆ์ผ๋ก ์์ฑ์ ์ฉ์ดํ๋๋ก @Builder๋ฅผ ํตํด ๋น๋ํจํด์ ์ ์ฉ์์ผ ์์ฑ์๋ฅผ ๋ง๋ค์ด์ค๋ค.
@GeneratedValue(strategy = GenerationType.IDENTITY)๋ก id ๊ฐ์ ์๋ ์์ฑ๋๋๋ก ์ค์ ํ๋ค.
2๏ธโฃ ์ต์ ์ํฐํฐ
@Entity
@Getter
@Table(name = "options")
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Option extends BaseEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "option_id")
private Long id;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "option_category_id")
private OptionCategory optionCategory;
@OneToMany(mappedBy = "option", cascade = CascadeType.ALL, orphanRemoval = true)
private List<ProdOption> prodOptions = new ArrayList<>();
private String name;
@Builder
private Option(OptionCategory optionCategory, String name) {
this.optionCategory = optionCategory;
this.name = name;
}
public void setOptionCategory(OptionCategory optionCategory){
this.optionCategory = optionCategory;
}
public void addProdOptions(ProdOption prodOption){
if (!prodOptions.contains(prodOption)) {
prodOptions.add(prodOption);
}
prodOption.setOption(this);
}
}
์ต์ : ์ํ-์ต์ ์กฐ์ธํ ์ด๋ธ = 1:N ์ด๊ธฐ๋๋ฌธ์ ์ญ์ @OneToMany๋ก ๊ด๊ณ์ค์ , cascade ์ต์ ์ผ๋ก ์์์ฑ ์ ์ด๋ฅผ ์ด์ฉํด ๊ด๋ จ๋ ์ํฐํฐ์ธ ์กฐ์ธ์ฉ ๊ฐ์ฒด์ ์ ํ์ํจ๋ค. ๋ํ, orphanRemoval ์ต์ ์ผ๋ก ์์ ๊ฐ์ฒด์ธ ์ํ-์ต์ ๊ฐ์ฒด๊ฐ ๊ณ ์์ผ ๊ฒฝ์ฐ ์๋์ผ๋ก ์ญ์ ํด์ฃผ๋ ์ญํ ์ ํ๋ค.
์ด ์ต์ ์ ํตํด ๋ฆฌ์์ค ๋ญ๋น๋ฅผ ์ค์ธ๋ค.
๋ถ๋ชจ ๊ฐ์ฒด๊ฐ ์ฌ๋ผ์ง ๊ฒฝ์ฐ, ๊ทธ๋ฆฌ๊ณ ์ฐ๊ด๊ด๊ณ๊ฐ ์ฌ๋ผ์ง ๊ฒฝ์ฐ ๋ชจ๋ ์ญ์ ๋ฅผ ํ๊ธฐ ์ํด์ ๋๋ค ์จ์ค๋ค.
-> ํด๋น ๋ด์ฉ์ ์ํ(Product Entity)์๋ ์ ์ฉ์์ผ ํ๋ฒ์ ์์ฒญ์ผ๋ก ์ธ๊ฐ์ ์ํฐํฐ๊ฐ ๊ด๋ฆฌ๋ ์ ์๋๋ก ํ๋ค. (์ํ,์ํ-์ต์ ,์ต์ )
3๏ธโฃ ์ํ-์ต์ ์ํฐํฐ
@Entity
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class ProdOption extends BaseEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "prod_option_id")
private Long id;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "product_id")
private Product product;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "option_id")
private Option option;
@Builder
private ProdOption(Long id,Product product, Option option) {
this.id = id;
this.product = product;
this.option = option;
}
public void setProduct(Product product) {
this.product = product;
}
public void setOption(Option option){
this.option = option;
}
}
์กฐ์ธ ํ ์ด๋ธ ํน์ฑ์ ๊ฐ์ง๊ณ ์๊ธฐ๋๋ฌธ์ @ManyToOne์ผ๋ก ์ค์ ์ ํด์ฃผ๊ณ , ์ง์ฐ๋ก๋ฉ์ ํตํด N+1์ ๋ฌธ์ ๋ฅผ ๋ฐฉ์งํด์ค๋ค.