관련 포스팅
2023.07.13 - [Spring/JPA] - 스프링) JPA Entity option 지연 로딩/영속성 전이/고아 entity삭제 (23-07-12)
지우고자 하는 데이터가 다른 테이블에서 FK로 사용 중이라면 지울 수 없다.
만약 지우려 하는 엔티티가 Device이고, Sensor가 Device FK를 가지고 있다면
- 연관된 Sensor를 삭제하던가
- 연관된 Sensor에서 Device FK를 NULL로 만들던가
어떤 방법으로든 먼저 Device에 종속되어 있는 관계성을 끊어야 Device를 지울 수 있다.
CascadeType.REMOVE
CascadeType.REMOVE - Device를 delete할 때, 연관된 Sensor를 자동으로 삭제한다.
// Device.java
@OneToOne(mappedBy = "device", cascade = CascadeType.REMOVE)
private Sensor sensor;
// Sensor.java
@OneToOne
@JoinColumn(name = "device_id", referencedColumnName = "id")
private Device device;
일대다도 마찬가지이고 부모쪽에서 쓰면 된다.
+) 외래키 주인에서 사용해도 상관없다. 암튼, cascade 코드가 있는 entity를 삭제할 때 연관 entity를 지운다.
orphanRemoval = true
REMOVE와 동일하게 부모쪽에서 쓰면 된다.
특성 | CascadeType.REMOVE | orphanRemoval = true |
작동 시점 | 부모 엔티티가 삭제될 때 | 자식 엔티티가 부모와의 관계에서 제거될 때 |
주 삭제 트리거 | 부모의 삭제 | 부모와의 관계가 끊어질 때 |
관계 해제 시 동작 | 자식 엔티티는 남아 있음 | 자식 엔티티는 삭제됨 |
명시적 삭제 필요 여부 | 부모의 명시적 삭제가 필요 | 관계가 끊어지면 자동 삭제 |
remove와 orphanRemoval의 차이를 gpt한테 물어보니 위 표를 줬다.
remove는 부모 엔티티 삭제가 트리거이고, 다른 방법으로 관계를 끊으면 고아 엔티티를 삭제하지 않는다.
orphanRemoval는 관계가 끊어지는 게 트리거이고, 어떤 방법이던 관계가 끊기면 고아 엔티티를 삭제한다.
// Device.java
@OneToMany(mappedBy = "device", orphanRemoval = true, cascade = CascadeType.PERSIST)
private List<Sensor> sensors = new ArrayList<>();
// Sensor.java
@ManyToOne
@JoinColumn(name = "device_id", referencedColumnName = "id")
private Device device;
확인해 보자.
// TestCode
@Test
@Transactional
@Rollback(value = false)
void delete() {
Optional<Device> byId = deviceRepository.findById(4L);
if (byId.isPresent()) {
Device device = byId.get();
List<Sensor> sensors = device.getSensors();
sensors.set(1, null);
deviceRepository.save(device);
}
}
부모 엔티티 삭제가 아닌 null 값을 넣어 관계를 끊어보면.
- CascadeType.REMOVE는 관계가 끊어져 사용되지 않는 Sensor 를 삭제하지 않고
- orphanRemoval = true는 고아 상태 Sensor 를 삭제한다.
어떤 비즈니스든 전산화 솔루션을 제공하면 주로 관계형 DB를 사용하고 많은 연관관계가 생긴다.
그러다 보면 연결할 FK를 빼먹거나, 끊어야 할 FK를 안 끊거나 할 수 있다.
복잡한 ERD일수록 CRUD를 재현하는 것도 시간이 걸리게 되는데, 그래도 테스트 짜다보면 꼭 놓치는 부분들이 보이는 것 같다.
'Spring > JPA' 카테고리의 다른 글
Spring Data JPA - flush(sql error 1062 sqlstate 23000) (4) | 2024.10.20 |
---|---|
JDBC, JPA, Hibernate, Spring Data JPA (0) | 2023.09.28 |
spring data JPA - slice, page (무한 스크롤, 페이지네이션) (0) | 2023.07.27 |
스프링) JPA Entity option 지연 로딩/영속성 전이/고아 entity삭제 (23-07-12) (0) | 2023.07.14 |
스프링) JPA Entity 연관관계 - 외래 키 주인 (23-07-11) (1) | 2023.07.14 |