๐ฅ CascadeType ์๋ฒฝ ์ ๋ฆฌ
๐ CascadeType ์ข ๋ฅ์ ์๋ฏธ
1. CascadeType.PERSIST
java
@OneToMany(cascade = CascadeType.PERSIST)
private List<OrderItem> orderItems;
// ๋์ ์์
Order order = new Order();
order.addItem(new OrderItem("์ํ1")); // ์๋ก์ด OrderItem
entityManager.persist(order); // โ
OrderItem๋ ์๋ ์ ์ฅ
์๋ฏธ: ๋ถ๋ชจ ์ ์ฅ ์ ์์๋ ์๋ ์ ์ฅ
2. CascadeType.MERGE
java
@OneToMany(cascade = CascadeType.MERGE)
private List<OrderItem> orderItems;
// ๋์ ์์
Order detachedOrder = getOrderFromSession(); // ์์์ฑ ์ปจํ
์คํธ์์ ๋ถ๋ฆฌ๋ ์ํ
detachedOrder.getItems().get(0).setPrice(1000); // ์์ ์์
entityManager.merge(detachedOrder); // โ
Order์ OrderItem ๋ชจ๋ ์
๋ฐ์ดํธ
์๋ฏธ: ๋ถ๋ชจ ๋ณํฉ ์ ์์๋ ์๋ ๋ณํฉ
3. CascadeType.REMOVE
java
@OneToMany(cascade = CascadeType.REMOVE)
private List<OrderItem> orderItems;
// ๋์ ์์
Order order = entityManager.find(Order.class, 1L);
entityManager.remove(order); // โ
OrderItem๋ค๋ ์๋ ์ญ์
์๋ฏธ: ๋ถ๋ชจ ์ญ์ ์ ์์๋ ์๋ ์ญ์
4. CascadeType.REFRESH
java
@OneToMany(cascade = CascadeType.REFRESH)
private List<OrderItem> orderItems;
// ๋์ ์์
Order order = entityManager.find(Order.class, 1L);
// ๋ค๋ฅธ ๊ณณ์์ DB ๋ฐ์ดํฐ๊ฐ ๋ณ๊ฒฝ๋จ
entityManager.refresh(order); // โ
Order์ OrderItem ๋ชจ๋ DB์์ ์ฌ๋ก๋ฉ
์๋ฏธ: ๋ถ๋ชจ ์๋ก๊ณ ์นจ ์ ์์๋ ์๋ ์๋ก๊ณ ์นจ
5. CascadeType.DETACH
java
@OneToMany(cascade = CascadeType.DETACH)
private List<OrderItem> orderItems;
// ๋์ ์์
Order order = entityManager.find(Order.class, 1L);
entityManager.detach(order); // โ
OrderItem๋ค๋ ์์์ฑ ์ปจํ
์คํธ์์ ๋ถ๋ฆฌ
์๋ฏธ: ๋ถ๋ชจ ๋ถ๋ฆฌ ์ ์์๋ ์๋ ๋ถ๋ฆฌ
6. CascadeType.ALL
java
@OneToMany(cascade = CascadeType.ALL)
private List<OrderItem> orderItems;
// ์์ ๋ชจ๋ cascade ๋์์ ํฌํจ
// = {PERSIST, MERGE, REMOVE, REFRESH, DETACH}
๐ฏ ์ค๋ฌด ์ฌ์ฉ ํจํด
โ ์์ ํ ํจํด๋ค
1. ์ ์ฅ๋ง cascade (๊ฐ์ฅ ์ผ๋ฐ์ )
java
@OneToMany(cascade = CascadeType.PERSIST)
private List<Category> customCategories;
// ์ฌ์ฉ๋ฒ
User user = new User();
user.addCategory(new Category("์๋น"));
userRepository.save(user); // Category๋ ์๋ ์ ์ฅ
2. ์ ์ฅ + ์์ cascade
java
@OneToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE})
private List<UserSetting> settings;
// ์์ ์์๋ ์์์ด ํจ๊ป ์ฒ๋ฆฌ๋จ
3. ๊ฐํ ๊ฒฐํฉ ๊ด๊ณ์์๋ง ์ญ์ cascade
java
// โ
์ฃผ๋ฌธ-์ฃผ๋ฌธ์ํ (์๋ช
์ฃผ๊ธฐ๊ฐ ๊ฐ์)
@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
private List<OrderItem> orderItems;
// โ
๊ฒ์๊ธ-์ฒจ๋ถํ์ผ
@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
private List<Attachment> attachments;
โ ์ํํ ํจํด๋ค
1. ์ฝํ ๊ฒฐํฉ์์ ALL ์ฌ์ฉ
java
// โ ์ํ: ์ฌ์ฉ์ ์ญ์ ์ ๋ชจ๋ ์ฃผ๋ฌธ์ด ์ญ์ ๋จ
@OneToMany(cascade = CascadeType.ALL)
private List<Order> orders;
// โ
๊ฐ์ : ์ญ์ ๋ ๋ณ๋ ์ฒ๋ฆฌ
@OneToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE})
private List<Order> orders;
2. ๋ค๋๋ค ๊ด๊ณ์์ CASCADE ์ฌ์ฉ
java
// โ ๋งค์ฐ ์ํ
@ManyToMany(cascade = CascadeType.ALL)
private List<Role> roles;
// โ
๋ค๋๋ค๋ cascade ์์ด
@ManyToMany
private List<Role> roles;
๐จ ์ค๋ฌด ์ฅ์ ์ฌ๋ก
์ฌ๋ก 1: ์์์น ๋ชปํ ์ญ์
java
// ๊ด๋ฆฌ์๊ฐ ํ
์คํธ ๊ณ์ ์ญ์
User testUser = userRepository.findByEmail("test@test.com");
userRepository.delete(testUser);
// ๐ฑ ๊ฒฐ๊ณผ: CascadeType.ALL ๋๋ฌธ์
// - ํ
์คํธ ์ฃผ๋ฌธ 100๊ฑด ์ญ์
// - ๊ด๋ จ ์ํ ๋ฆฌ๋ทฐ ์ญ์
// - ์ฟ ํฐ ์ฌ์ฉ ์ด๋ ฅ ์ญ์
์ฌ๋ก 2: ์ฑ๋ฅ ๋ฌธ์
java
// ์นดํ
๊ณ ๋ฆฌ ํ๋ ์ญ์
Category category = categoryRepository.findById(1L);
categoryRepository.delete(category);
// ๐ฑ CascadeType.ALL๋ก ์ธํด
// - 10,000๊ฐ UserCategoryVisibility ์กฐํ
// - ๊ฐ๊ฐ ๊ฐ๋ณ DELETE ์ฟผ๋ฆฌ ์คํ
// - 30์ด ์๋ต ์ง์ฐ → ํ์์์
๐ก๏ธ ์ค๋ฌด ๊ฐ์ด๋๋ผ์ธ
1. Cascade ์ ํ ๊ธฐ์ค
๊ด๊ณ ์ ํ๊ถ์ฅ Cascade์์
๊ฐํ ๊ฒฐํฉ | ALL | ์ฃผ๋ฌธ↔์ฃผ๋ฌธ์ํ, ๊ฒ์๊ธ↔์ฒจ๋ถํ์ผ |
์ผ๋ฐ์ ๋ถ๋ชจ-์์ | {PERSIST, MERGE} | ์ฌ์ฉ์↔์ค์ , ์นดํ ๊ณ ๋ฆฌ↔๊ฐ์์ฑ |
์ฝํ ๊ฒฐํฉ | PERSIST ๋๋ ์์ | ์ฌ์ฉ์↔์ฃผ๋ฌธ, ์นดํ ๊ณ ๋ฆฌ↔์ํ |
๋ค๋๋ค | ์์ | ์ฌ์ฉ์↔์ญํ , ์ํ↔์นดํ ๊ณ ๋ฆฌ |
2. orphanRemoval ์ฌ์ฉ ๊ธฐ์ค
java
// โ
๋ถ๋ชจ์์ ์ ๊ฑฐ๋๋ฉด ์์๋ ์ญ์ ๋์ด์ผ ํ๋ ๊ฒฝ์ฐ
@OneToMany(cascade = {PERSIST, MERGE}, orphanRemoval = true)
private List<UserSetting> settings;
// โ ๋
๋ฆฝ์ ์ผ๋ก ์กด์ฌํ ์ ์๋ ๊ฒฝ์ฐ
@OneToMany(cascade = {PERSIST, MERGE}, orphanRemoval = false)
private List<Order> orders;
3. ์ค๋ฌด ์ฒดํฌ๋ฆฌ์คํธ
java
// โ
์ข์ ์์
@OneToMany(
mappedBy = "user",
cascade = {CascadeType.PERSIST, CascadeType.MERGE}, // ๋ช
์์ ์ง์
orphanRemoval = true, // ํ์ํ ๊ฒฝ์ฐ๋ง
fetch = FetchType.LAZY // ์ง์ฐ ๋ก๋ฉ
)
private List<UserSetting> settings = new ArrayList<>();
// โ ๋์ ์์
@OneToMany(
cascade = CascadeType.ALL, // ๋๋ฌด ๊ด๋ฒ์
fetch = FetchType.EAGER // ์ฑ๋ฅ ๋ฌธ์
)
private List<Order> orders;
๐ฏ ํต์ฌ ์์น
- ๊ธฐ๋ณธ์ ์ผ๋ก cascade ์ต์ํ
- ์ญ์ ๋ ๋ช ์์ ์ผ๋ก ์ฒ๋ฆฌ
- ๊ฐํ ๊ฒฐํฉ ๊ด๊ณ์๋ง ALL ์ฌ์ฉ
- ๋ค๋๋ค์๋ cascade ์ฌ์ฉ ๊ธ์ง
- ์ฝ๋๋ฆฌ๋ทฐ ์ cascade ๊ทผ๊ฑฐ ๋ช ์