본문 바로가기
Spring

[TIL] 240412 즉시로딩, 지연로딩, 영속성 전이, OrphanRemoval

by studymode 2024. 4. 12.

즉시로딩 지연로딩 FetchType

  • 연관관계 entity를 바로 가져오거나 (즉시로딩 / FetchType = Eager), 필요할 때 가져옴 (지연로딩 / FetchType = Lazy)
  • 기본적으로 @OneToMany는 Lazy (가져올 값이 많으니까(리스트)필요할때), 
  • @ManyToOne은 Eager 이 default
  • FetchType=lazy는 @Transactional 걸어줘야 함
    • 지연로딩도 연속성 컨텍스트의 기능 중 하나
    • 지연로딩된 entity의 정보를 조회할 땐 영속성 컨텍스트가 존재해야함
    • 영속성 컨텍스트 존재하기 위해 트렌젝션이 적용되어야함

 

 

 

영속성 전이 Cascade

  • 영속 상태의 Enity에서 수행되는 작업들이 연관된 entity까지 전파되는 상황
  • cascade persist옵션으로 설정
  • cascade: remove를 통해 연관 entity의 정보 (음식과 유저 정보) 한번에 삭제 가능
  • Cacade옵션을 Persist와 Remove를 중복으로 설정할 수 있음
    • cascade = {CascadeType.PERSIST, CascadeType.REMOVE}

🔽 User entity에 foode cascade persist 설정 코드

@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);// 외래 키(연관 관계) 설정
		}
}

 

user entity의 연관 entity인 food와 연관관계를 설정할 때

cascade = CascadeType.PERSIST 설정

 

 

🔽 영속성전이 설정 이전 코드

@Test
@DisplayName("Robbie 음식 주문")
void test1() {
    // 고객 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);
    foodRepository.save(food);
    foodRepository.save(food2);
}

user repository와 food repository각각 save 해줘야함

 

🔽 영속성전이 설정 이후 코드

@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를 설정함으로서 직접 food entity객체를 영속 상태로 만들지 않아도 자동 저장 됨

User, Food, Food2를 세번 저장하는 코드에서

userRepository만 저장하는 코드로 바뀜

 

 

 

🔽 Cacade Remove 

@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);// 외래 키(연관 관계) 설정
    }
}

 

Cacade옵션을 Persist와 Remove를 중복으로 설정할 수 있음

 

 

 OrphanRemoval 고아 Entity 삭제

  • 연관 entity 삭제 기능

 

🔽 orphanRemoval True

@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);// 외래 키(연관 관계) 설정
    }
}

user와 연관 entity인 food에 대하여 orphanRemoval = true 설정

 

 

CascadeType.REMOVE와 orphanRemoval=true 의 차이

CascadeType.REMOVE

  • 부모 엔티티가 삭제될 때 연관 자식 엔티티도 함께 삭제
  • Post가 삭제되면 관련 Comment도 함께 삭제

 

orphanRemoval=true

  • 부모 엔티티와의 연관 관계가 끊어진 자식 엔티티를 자동으로 삭제
  • 부모 엔티티의 컬렉션에서 자식 엔티티를 제거하면, 해당 자식 엔티티는 데이터베이스에서도 삭제
  • Order와 OrderItem의 관계에서 특정 주문 항목을 제거하면, 해당 주문 항목이 데이터베이스에서도 삭제되어야 하는 경우에 사용