Spring

CascadeType.MERGE

MDanderson 2023. 4. 26. 06:08

CascadeType.MERGE는 부모 엔티티가 병합(merge)될 때, 연관된 자식 엔티티도 함께 병합되도록 하는 설정입니다.

병합(merge)이란, 준영속 상태의 엔티티를 다시 영속화하고, 변경사항을 데이터베이스에 반영하는 과정을 말합니다. 준영속 상태란, 영속성 컨텍스트에서 관리되던 엔티티가 영속성 컨텍스트와의 관계를 끊고, 더 이상 영속성 컨텍스트가 관리하지 않는 상태를 의미합니다.

예시 코드를 통해 CascadeType.MERGE를 설명하겠습니다.

위의 예제에서 Parent 엔티티의 children 필드에 CascadeType.MERGE가 설정되어 있습니다. 이 말은, Parent 엔티티가 병합될 때 연관된 Child 엔티티들도 함께 병합되도록 설정되어 있다는 것입니다.

예를 들어, 다음과 같이 Parent와 Child 객체를 생성하고 연관 관계를 설정한 후에, Parent 엔티티를 병합하는 경우입니다.

위 코드에서 entityManager.merge(parent)를 호출할 때, 준영속 상태의 Parent 엔티티가 다시 영속화되고, 연관된 Child 엔티티들도 CascadeType.MERGE 설정 때문에 함께 병합됩니다. 이렇게 함께 병합된 Child 엔티티들의 변경사항도 데이터베이스에 반영됩니다.

예를 들어, 다음과 같이 Child 객체를 수정한 후에, Parent 엔티티를 병합하는 경우입니다.

위 코드에서 entityManager.merge(parent)를 호출할 때, 준영속 상태의 Parent 엔티티와 그에 연관된 Child 엔티티들이 다시 영속화되고, 모든 변경사항이 데이터베이스에 반영됩니다. CascadeType.MERGE 설정으로 인해, Parent 엔티티를 병합하는 동시에 연관된 Child 엔티티들의 변경사항도 함께 병합되고 데이터베이스에 반영됩니다.

이처럼 CascadeType.MERGE를 사용하면, 부모 엔티티를 병합할 때 연관된 자식 엔티티들도 함께 병합되도록 설정할 수 있어, 관련 엔티티들의 동기화를 쉽게 유지할 수 있습니다.

 

스프링 부트 JPA에서 CascadeType.MERGE를 사용하는 예시를 들겠습니다. 앞서 사용했던 Author와 Book 엔티티 클래스를 사용하겠습니다.

먼저, Author 엔티티에서 CascadeType.MERGE를 추가합니다.

이제 기존의 저자(Author)와 그에 속한 책(Book)들의 정보를 업데이트하는 예시를 작성해보겠습니다. AuthorService 클래스에서 기존 저자와 책들의 정보를 업데이트하는 메서드를 작성합니다.

@Service
public class AuthorService {
    @Autowired
    private AuthorRepository authorRepository;

    // ... addAuthorWithBooks method ...

    @Transactional
    public void updateAuthorWithBooks(Long authorId, String updatedAuthorName, Map<Long, String> updatedBooks) {
        Author author = authorRepository.findById(authorId).orElseThrow(() -> new RuntimeException("Author not found"));

        // Update author's name
        author.setName(updatedAuthorName);

        // Update books' titles
        for (Map.Entry<Long, String> entry : updatedBooks.entrySet()) {
            Long bookId = entry.getKey();
            String updatedTitle = entry.getValue();

            Book book = author.getBooks().stream()
                    .filter(b -> b.getId().equals(bookId))
                    .findFirst()
                    .orElseThrow(() -> new RuntimeException("Book not found"));

            book.setTitle(updatedTitle);
        }

        // CascadeType.MERGE를 사용하면, author 엔티티와 연관된 book 엔티티들이 함께 병합됩니다.
        authorRepository.save(author);
    }
}

 

이 예시에서는 Author 엔티티를 병합할 때, CascadeType.MERGE가 설정되어 있으므로, Book 엔티티들도 함께 병합됩니다. 이렇게 하면, 부모 엔티티와 자식 엔티티를 한 번의 병합 작업으로 처리할 수 있습니다.