본문 바로가기
내일배움캠프

내일배움캠프TIL- 영속성 전이

by Kiwimel0n 2024. 1. 30.

엔티티의 관계에 대해 일대일 , 일대 다 , 다 대 일, 대 대 다를 배우게 되면서 이렇게 관계된 객체들을 쉽게 관리하고  처리를 하기 위해 영속성 전이라는 것을 알아보겠다.

 

영속성 전이 : CASCADE

영속성 전이 기능은 특정 엔티티를 영속 상태로 만들 때, 연관 엔티티도 영속 상태로 만들고 싶은 경우 사용한다.

JPA 에선는 CASCADE 옵션으로 영속성 전이를 제공한다.

영속성 전이를 사용하면, 부모 엔티티를 저장할 때 자식 엔티티도 함께 저장할 수 있다는 것이다.

 

예를들어

음식 테이블 과 고객 테이블이 N : 1 양방향 관계라고 가정한다면

Food 엔티티

@Entity
@Table(name = "food")
public class Food {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;
    private double price;

    @ManyToOne
    @JoinColumn(name = "user_id")
    private User user;
}

 

 

User엔티티

@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)
    private List<Food> foodList = new ArrayList<>();

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

고객 Entity의 @OneToMany 애너테이션에 영속성 전이를 적용해서 음식 Entity도 자동으로 저장될 수 있도록 만든다.

@Test
@DisplayName("영속성 전이 저장")
void test2() {
    // 고객 Robbie 가 후라이드 치킨과 양념 치킨을 주문합니다.
    User user = new User();
    user.setName("Robbie");

    // 후라이드 치킨 주문
    Food food = new Food();
    food.setName("후라이드 치킨");
    food.setPrice(15000);

    user.addFoodList(food);

    Food food2 = new Food();
    food2.setName("양념 치킨");
    food2.setPrice(20000);

    user.addFoodList(food2);

    userRepository.save(user);
}

영속성 저장으로 CASCADE PERSIST옵션을 적용했기 때문에 직접 음식 Entity 객체 food, food2를 영속 상태로 만들지 않아도 자동으로 저장이된다.

 

 

 

 

이번에는 영속성 전이의 REMOVE 옵션을 사용하기 위하여 

USER 엔티티에 

@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, CascadeType.REMOVE})
    private List<Food> foodList = new ArrayList<>();

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

 

cascade = {CascadeType.PERSIST, CascadeType.REMOVE} 이렇게 중복으로 옵션을 설정한다.

고객 Entity의 @OneToMany 애너테이션에 연관된 음식 Entity도 자동으로 삭제될 수 있도록 REMOVE 옵션을 추가.

 

@Test
@Transactional
@Rollback(value = false)
@DisplayName("영속성 전이 삭제")
void test4() {
    // 고객 Robbie 를 조회합니다.
    User user = userRepository.findByName("Robbie");
    System.out.println("user.getName() = " + user.getName());

    // Robbie 가 주문한 음식 조회
    for (Food food : user.getFoodList()) {
        System.out.println("food.getName() = " + food.getName());
    }

    // Robbie 탈퇴
    userRepository.delete(user);
}

 

Robbie 고객 Entity 객체를 조회한 후 해당 객체를 delete 하자 자동으로 연관된 음식 데이터들이 삭제된다.

 

 

 

이것 외 에도 CASCADE 종류로는 아래의 표와 같이 몇가지가 더 있다.

 

CASCADE 종류 설명
PRESIST 부모 엔티티가 영속화 될때 자식 엔티티도 영속화
MERGE 부모 엔티티가 병합될때 자식 엔티티도 병합
REMOVE 부모 엔티티가 삭제될때 자식 엔티티도 삭제
REFRESH 부모 엔티티가 refresh 되면 자식엔티티도 refresh
DETACH 부모 엔티티가 DETACH 되면 자식 엔티티도 DETACH상태로 변경
ALL 부모 엔티티의 영속성 상태 변화를 자식 엔티티에 모두 전이