💡 JPA 연관관계가 존재할 때 Entity 삭제하기
JPA 프로젝트를 진행하던 중, 회원 탈퇴를 진행할 때 User와 그에 연관된 Entity에서 @ManyToOne 관계에서 영속성 관리에서 문제가 발생되었다.
그냥 User Data를 delete하려고하면 다음과 같은 Error가 발생한다.
Cannot delete or update a parent row: a foreign key constraint fail
참조된 객체를 지워주지 않았기 때문에 발생하였다.
처음에는 @ManyToOne
어노테이션에 cascade
option을 부여해서 영속성을 부여 해 보았다.
그러나 User를 Delete할 때 위와 같은 오류가 계속해서 발생했다.
결론적으로 찾은 이유는 내가 단방향으로 child
에게 parent
만을 Mapping했기 때문이다.
parent
는 child
를 매핑하지 않았기 때문에 계단식으로 데이터가 삭제되는데 실패했다.
그래서 둘을 양방향으로 연결 해 주는 것을 우선적으로 해야했다.
@OneToMany
어노테이션으로 parent
Entity에 List나 Set 형식으로 child
를 Mapping 해 주었다.
나는 이 부분 때문에 계속
Caused by: org.hibernate.AnnotationException: mappedBy reference an unknown target entity property
에러가 발생했었는데 변수명을 일치시키지 않아서 생긴 문제였다.
@Entity
@Getter
@Setter
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
...
@OneToMany(mappedBy = "userId", cascade = {CascadeType.ALL}, orphanRemoval=true)
private List<UserConference> userConferences;
....
}
@Entity
@Getter
@Setter
public class UserConference {
...
@ManyToOne
@JoinColumn(name="User_ID", referencedColumnName = "ID")
private User userId;
}
위와 같이 mappedBy는 child의 변수명과 일치시켜야한다.
모든 관계에 대해서 양방향 설정을 마치고,
cascade 옵션을 ALL로 주었다.
위 과정을 마친 후 유저 삭제가 계단식으로 잘 처리 되는 것을 확인하였다.
CascadeType.PERSIST
엔티티를 영속화 할 때이 필드에 보유 된 엔티티도 유지합니다. EntityManager가 flush 중에 새로운 엔티티를 참조하는 필드를 찾고이 필드가 CascadeType.PERSIST를 사용하지 않으면 오류이므로이 Cascade 규칙의 자유로운 적용을 제안합니다.
CascadeType.MERGE
엔티티 상태를 병합 할 때, 이 필드에 보유 된 엔티티도 병합하십시오.
CascadeType.REFRESH
엔티티를 새로 고칠 때, 이 필드에 보유 된 엔티티도 새로 고칩니다.
CascadeType.REMOVE
엔티티를 삭제할 때, 이 필드에 보유 된 엔티티도 삭제하십시오.
CascadeType.DETACH
부모 엔티티가 detach()를 수행하게 되면, 연관된 엔티티도 detach() 상태가 되어 변경사항이 반영되지 않는다.
CascadeType.ALL
모든 Cascade 적용