Spring/팀스파르타

42. 고아 Entity 삭제

열심히 해 2024. 12. 6. 14:55

orphanRemoval

  • CASCADE의 REMOVE 옵션을 적용하면 해당 Entity 객체를 삭제 했을 때 연관된 Entity 객체들을 자동으로 삭제할 수 있었습니다.
  • 하지만 REMOVE 옵션 같은 경우 연관된 Entity와 관계를 제거했다고 해서 자동으로 해당 Entity가 삭제 되지는 않습니다.

 

테스트를 위한 데이터 넣기.

@SpringBootTest
public class OrphanTest {

    @Autowired
    UserRepository userRepository;
    @Autowired
    FoodRepository foodRepository;

    @Test
    @Transactional
    @Rollback(value = false)
    void init() {
        List<User> userList = new ArrayList<>();
        User user1 = new User();
        user1.setName("Robbie");
        userList.add(user1);

        User user2 = new User();
        user2.setName("Robbert");
        userList.add(user2);
        userRepository.saveAll(userList);

        List<Food> foodList = new ArrayList<>();
        Food food1 = new Food();
        food1.setName("고구마 피자");
        food1.setPrice(30000);
        food1.setUser(user1); // 외래 키(연관 관계) 설정
        foodList.add(food1);

        Food food2 = new Food();
        food2.setName("아보카도 피자");
        food2.setPrice(50000);
        food2.setUser(user1); // 외래 키(연관 관계) 설정
        foodList.add(food2);

        Food food3 = new Food();
        food3.setName("후라이드 치킨");
        food3.setPrice(15000);
        food3.setUser(user1); // 외래 키(연관 관계) 설정
        foodList.add(food3);

        Food food4 = new Food();
        food4.setName("양념 치킨");
        food4.setPrice(20000);
        food4.setUser(user2); // 외래 키(연관 관계) 설정
        foodList.add(food4);

        Food food5 = new Food();
        food5.setName("고구마 피자");
        food5.setPrice(30000);
        food5.setUser(user2); // 외래 키(연관 관계) 설정
        foodList.add(food5);
        foodRepository.saveAll(foodList);
    }

    @Test
    @Transactional
    @Rollback(value = false)
    @DisplayName("연관관계 제거")
    void test1() {
        // 고객 Robbie 를 조회합니다.
        User user = userRepository.findByName("Robbie");
        System.out.println("user.getName() = " + user.getName());

        Food chicken = null;
        for (Food food : user.getFoodList()) {
            if(food.getName().equals("후라이드 치킨")) {
                chicken = food;
            }
        }
        if(chicken != null) {
            user.getFoodList().remove(chicken);  // 연관된 음식 Entity 제거 : 후라이드 치킨
        }

        // 연관관계 제거 확인
        for (Food food : user.getFoodList()) {
            System.out.println("food.getName() = " + food.getName());
        }
    }
}

 

1. orphanRemoval 적용하지 않았을 때 테스트 실행

 

 

고객 Robbie(user_id = 1)는 고구마 피자, 아보카도 피자, 후라이드 치킨을 가지고 있었습니다.

 

예상대로 후라이드 치킨을 제외하고 출력했습니다.

 

하지만 데이터 베이스에서는 삭제되지 않았습니다.

 

 

 

 

 

2. orphanRemoval 적용한 후 테스트 실행

 

@Entity
@Getter
@Setter
@Table(name = "users")
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;

    @OneToMany(mappedBy = "user", cascade = CascadeType.PERSIST, orphanRemoval = true)
    private List<Food> foodList = new ArrayList<>();

    public void addFoodList(Food food) {
        this.foodList.add(food);
        food.setUser(this); // 외래 키 설정
    }
}

 

 

 

orphanRemoval 적용 후 delete 쿼리가 실행됩니다.

 

데이터 베이스에서도 삭제된 것을 확인할 수 있습니다.

 

 

 

 

 


 

정리

`1 : n = 고객 : 음식(fk)`

 

Cascade = CascadeType.REMOVE 적용 시

 

1. 특정 고객 삭제 시 음식 데이터도 삭제됩니다.

2. 특정 고객이 갖는 foodList 에서 특정 food 를 골라서 데이터베이스에서 삭제할 수 없습니다.

 

 

orphanRemoval = Ture 적용 시

 

1. 특정 고객 삭제 시 음식 데이터도 삭제됩니다. 

2. 특정 고객이 갖는 foodList 에서 특정 food 를 골라서 데이터베이스에서 삭제할 수 있습니다.

'Spring > 팀스파르타' 카테고리의 다른 글

44. Mockito  (0) 2024.12.06
43. 단위 테스트  (0) 2024.12.06
41. 영속성 전이  (0) 2024.12.06
40. 즉시 로딩, 지연 로딩과 영속성 컨텍스트  (0) 2024.12.06
39. Entity 연관관계 - N 대 M  (0) 2024.12.06