본문 바로가기
Server/🌱 Spring Boot (java)

[Spring boot jpa] 찜/좋아요 삭제시 연관된 엔티티도 같이 삭제되는 문제 해결

by 코딩하는 동현😎 2025. 1. 25.

상황

사용자가 특정 House에 대해 찜을 해제하려고 할 때, Pin 엔티티가 삭제되어야 하는데, 의도치 않게 UserHouse 엔티티까지 삭제되는 문제가 발생했습니다.


원인

@ManyToOne 관계에 설정된 cascade = CascadeType.ALL은 부모 엔티티에서 발생하는 모든 영속성(Persistence) 작업(예: PERSIST, MERGE, REMOVE 등)을 연관된 자식 엔티티에도 전파하도록 지정한다.

house와 user는 @ManyToOne 관계에서 Pin과 연관되어 있으며, CascadeType.ALL로 설정되어 있습니다. 따라서 Pin 삭제 시 JPA는 이 연관된 엔티티들도 함께 삭제하도록 동작한다.

pinRepository.deleteByUserAndHouse(user, house); // 여기서 삭제 됨

@Entity
@Table(name="pin")
@Data
public class Pin {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    @JoinColumn(name = "house_id")
    private House house;

    @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    @JoinColumn(name = "user_id")
    private User user;
}

CascadeType은 JPA에서 연관 관계를 맺고 있는 엔티티들 간에 특정 작업을 어떻게 전파할지 설정하는 옵션이다. 주로 부모 엔티티에서 수행된 작업이 자식 엔티티에 전파되도록 하기 위해 사용된다.


CascadeType 종류

  1. PERSIST: 부모 엔티티가 저장될 때, 연관된 자식 엔티티도 저장된다. 예를 들어, CascadeType.PERSIST를 설정하면 부모 엔티티를 저장할 때 자식 엔티티도 자동으로 저장된다.
  2. MERGE: 부모 엔티티가 병합될 때, 연관된 자식 엔티티도 병합된다. 부모 엔티티가 병합될 때 자식 엔티티의 상태도 반영된다.
  3. REMOVE: 부모 엔티티가 삭제될 때, 연관된 자식 엔티티도 삭제된다. 부모 엔티티를 삭제할 때 연관된 자식 엔티티도 함께 삭제된다.
  4. REFRESH: 부모 엔티티가 리프레시될 때, 연관된 자식 엔티티도 리프레시된다. 부모 엔티티의 상태가 DB와 일치하도록 갱신될 때 자식 엔티티도 갱신된다.
  5. DETACH: 부모 엔티티가 분리될 때, 연관된 자식 엔티티도 분리된다. 부모 엔티티가 영속성 컨텍스트에서 분리되면 자식 엔티티도 함께 분리된다.
  6. ALL: 모든 작업이 자식 엔티티에 전파된다. 즉, PERSIST, MERGE, REMOVE, REFRESH, DETACH 모두 자식 엔티티에 전파된다.

해결

CascadeType.PERSIST 로 설정하여 저장될때만 연관되고, 삭제될땐 pin말고 다른 엔티티도 전파되지 않도록 설정합니다.

@Entity
@Table(name="pin")
@Data
public class Pin {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.PERSIST)
    @JoinColumn(name = "house_id")
    private House house;

    @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.PERSIST)
    @JoinColumn(name = "user_id")
    private User user;
}
반응형

댓글