[Spring Boot] Cascade

handa·2024년 12월 16일
0
post-thumbnail

Spring Boot에서 Cascade란

Spring Boot JPA에서 Cascade는 엔티티 간의 연관 관계에서, 하나의 엔티티에 대한 작업(예: 저장, 삭제 등)이 연관된 다른 엔티티에도 전이(Cascade)되도록 설정하는 기능입니다. 이를 통해 관계된 엔티티들을 자동으로 관리할 수 있습니다.


Cascade의 필요성

예를 들어, 두 엔티티 UserProfile@OneToOne 관계를 갖는다고 가정해봅시다. 만약 User 를 저장하면서 동시에 Profile 도 저장하려면 일반적으로 다음과 같은 코드가 필요합니다.

Profile profile = new Profile();
profile.setBio("Developer");
profileRepository.save(profile);

User user = new User();
user.setName("John");
user.setProfile(profile);
userRepository.save(user);

위 코드는 효율적이지 않습니다. 이를 개선하기 위해Cascade를 설정하면 User 엔티티를 저장하거나 삭제할 때 Profile 엔티티도 자동으로 저장되거나 삭제됩니다.


Cascade의 주요 유형

cascade 는 JPA의 @OneToOne, @OneToMany, @ManyToOne, @ManyToMany 관계에서 사용됩니다. CascadeType 은 다음과 같은 여러 옵션을 제공합니다.

1. ALL

  • 모든 Cascade 작업(저장, 병합, 제거 등)을 전이합니다.
@OneToOne(cascade = CascadeType.ALL)
private Profile profile;

2. PERSIST

  • 부모 엔티티가 저장될 때(수정도 포함) 연관된 자식 엔티티도 함께 저장됩니다.
@OneToOne(cascade = CascadeType.PERSIST)
private Profile profile;

3. MERGE

  • 부모 엔티티가 병합(업데이트)될 때 연관된 자식 엔티티도 병합됩니다.
@OneToOne(cascade = CascadeType.MERGE)
private Profile profile;

4. REMOVE

  • 부모 엔티티가 삭제되면 연관된 자식 엔티티도 삭제됩니다.
@OneToOne(cascade = CascadeType.REMOVE)
private Profile profile;

5. REFRESH

  • 부모 엔티티가 새로 고쳐질 때 연관된 자식 엔티티도 새로 고쳐집니다.
@OneToOne(cascade = CascadeType.REFRESH)
private Profile profile;

6. DETACH

  • 부모 엔티티가 영속성 컨텍스트에서 분리될 때 연관된 자식 엔티티도 분리됩니다.
@OneToOne(cascade = CascadeType.DETACH)
private Profile profile;

Cascade의 실제 사용 예

1. 연관 엔티티 저장

CascadeType.PERSIST 를 사용하면 부모 엔티티를 저장할 때 연관된 엔티티도 자동으로 저장됩니다.

@Entity
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @OneToOne(cascade = CascadeType.PERSIST)
    private Profile profile;

    // Getters and setters
}

@Entity
public class Profile {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String bio;

    // Getters and setters
}

// 실행 코드
Profile profile = new Profile();
profile.setBio("Developer");

User user = new User();
user.setName("John");
user.setProfile(profile);

userRepository.save(user); // User와 Profile이 모두 저장됨

2. 연관 엔티티 삭제

CascadeType.REMOVE 를 사용하면 부모 엔티티가 삭제될 때 연관된 자식 엔티티도 자동으로 삭제됩니다.

@Entity
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @OneToOne(cascade = CascadeType.REMOVE)
    private Profile profile;

    // Getters and setters
}

@Entity
public class Profile {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String bio;

    // Getters and setters
}

// 실행 코드
User user = userRepository.findById(1L).orElseThrow();
userRepository.delete(user); // User와 연관된 Profile도 삭제됨

3. 여러 Cascade 옵션 조합

Cascade 옵션은 여러 개를 조합하여 사용할 수도 있습니다.

@OneToOne(cascade = {CascadeType.PERSIST, CascadeType.MERGE})
private Profile profile;

Cascade와 연관된 주의점

  1. 부주의한 ALL 사용
    • CascadeType.ALL은 모든 Cascade 작업을 수행하므로, 예상치 못한 삭제나 병합 등이 발생할 수 있습니다.
    • 반드시 의도에 맞게 사용해야 합니다.
  2. CascadeType.REMOVE 주의
    • 부모 엔티티를 삭제할 때 연관된 모든 자식 엔티티가 삭제되므로, 데이터 손실 가능성을 유의해야 합니다.
  3. LAZY 로딩과의 조합
    • 관계가 Lazy Fetch로 설정된 경우, 연관된 엔티티를 명시적으로 초기화해야 Cascade가 제대로 작동합니다.
  4. 양방향 연관 관계
    • 양방향 관계에서 부모와 자식 엔티티 간의 mappedBycascade 설정을 명확히 해야 순환 참조 문제가 발생하지 않습니다.

profile
진짜 해보자

0개의 댓글