본문 바로가기
Java & Kotlin/Spring Data

[JPA] Cascade persist와 연관관계

by heekng 2022. 6. 24.
반응형

Cascade.persist와 연관관계

JPA를 배우고, 개발을 진행하면서 자주 사용하지 않을거라 생각한 cascade.persist에 대해 정리하려 한다.

[JPA]영속성 전이 CASCADE에서 정리했다시피 Cascade.persist 옵션은 부모를 영속화할 때 자식도 영속화하는 옵션이다.

예를 들어 부모 Entity에 oneToMany관계인 자식 Entity를 List로 넣어두고, 부모 Entity를 영속화(persist)한다면 자식 Entity도 연쇄적으로 persist되는 것이다.

주의하고자 하는 부분

하지만 단순히 부모 Entity에 자식 Entity를 넣어주는것 만으로는 정확한 Persist가 이루어지지 않는다.

자세하게 예를 들어보자.

먼저 Home과 Person은 1 : N 관계로 Cascade.ALL으로 설정되어 Cascade.persist가 적용된 상태이다.

// Home
public void addPerson(Person person) {
    this.persons.add(person);
}

///////////////

@Test
void cascadePersistTest() throws Exception {
    //given
    Home home = Home.builder()
            .name("homeName")
            .build();
    Person person = Person.builder()
            .name("person")
            .build();
    home.addPerson(person);
    em.persist(home);
    //when
    Person findPerson = em.find(Person.class, person.getId());
    //then
    assertThat(findPerson.getHome().getId()).isEqualTo(home.getId());
}

위처럼 Home 엔티티에 Person 엔티티를 add해주고, HomeEntity만 persist한다면?

위와 같이 findPerson.getHome()에서 NullPointException이 발생한다.

이 이유는 Home.addPerson() 메서드에 있다.

// Home
public void addPerson(Person person) {
    this.persons.add(person);
}

위 메서드를 통해 home의 persons 리스트에 person이 추가되어 persist가 연쇄되어 발생한다.
하지만 add 되는 person의 home에는 어떠한 엔티티도 할당되지 않았기 때문에, person은 homeId를 가지고 있지 않는다.

// System.out.println("home = " + home);
home = Home(id=1, name=homeName, dogs=[], persons=[Person(id=1, name=person, home=null)])
// System.out.println("person = " + person);
person = Person(id=1, name=person, home=null)

개선방법

위와 같은 상황을 피하기 위해 다음과 같이 addPerson 메서드를 수정하자.

public void addPerson(Person person) {
    person.setHome(this);
    this.persons.add(person);
}

위과 같이 addperson 메서드에 person의 home에 home 객체를 넣어준다면 정상적으로 테스트에 통과하게 된다.

반응형