반응형
JPA에는 고아 객체 라는 게 있다.
@Entity
@Getter
@Setter
@Table(name = "users")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
@OneToMany(mappedBy = "user", cascade = CascadeType.PERSIST)
private List<Food> foodList = new ArrayList<>();
public void addFoodList(Food food) {
this.foodList.add(food);
food.setUser(this);
}
}
@Entity
@Getter
@Setter
@Table(name = "food")
public class Food {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private double price;
@ManyToOne
@JoinColumn(name = "user_id")
private User user;
}
우선 이렇게 유저와 음식 엔티티가 있고,
Food 디비에는 후라이드 치킨을 포함한 5개의 요소가 있다면,
@Test
@Transactional
@Rollback(value = false)
@DisplayName("연관관계 제거")
void test1() {
// 고객 Robbie 를 조회합니다.
User user = userRepository.findByName("Robbie");
System.out.println("user.getName() = " + user.getName());
// 연관된 음식 Entity 제거 : 후라이드 치킨
Food chicken = null;
for (Food food : user.getFoodList()) {
if(food.getName().equals("후라이드 치킨")) {
chicken = food;
}
}
if(chicken != null) {
user.getFoodList().remove(chicken);
}
// 연관관계 제거 확인
for (Food food : user.getFoodList()) {
System.out.println("food.getName() = " + food.getName());
}
}
이 테스트 코드를 실행하면
Hibernate:
/* <criteria> */ select
u1_0.id,
u1_0.name
from
users u1_0
where
u1_0.name=?
user.getName() = Robbie
Hibernate:
select
fl1_0.user_id,
fl1_0.id,
fl1_0.name,
fl1_0.price
from
food fl1_0
where
fl1_0.user_id=?
food.getName() = 고구마 피자
food.getName() = 아보카도 피자
다음과 같이, 유저의 foodList 에는 삭제가 되었지만 실제로는 DB에 후라이드 치킨이 남아있는 것을 볼 수 있다.
@Entity
@Getter
@Setter
@Table(name = "users")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
@OneToMany(mappedBy = "user", cascade = CascadeType.PERSIST, orphanRemoval = true)
private List<Food> foodList = new ArrayList<>();
public void addFoodList(Food food) {
this.foodList.add(food);
food.setUser(this);
}
}
하지만 유저 엔티티에서 @OneToMany 속의 속성에 orphanRemoval 을 true 로 두면,
Hibernate:
/* <criteria> */ select
u1_0.id,
u1_0.name
from
users u1_0
where
u1_0.name=?
user.getName() = Robbie
Hibernate:
select
fl1_0.user_id,
fl1_0.id,
fl1_0.name,
fl1_0.price
from
food fl1_0
where
fl1_0.user_id=?
food.getName() = 고구마 피자
food.getName() = 아보카도 피자
Hibernate:
/* delete for com.sparta.jpaadvance.entity.Food */delete
from
food
where
id=?
후라이드 피자가 삭제된 것을 볼 수 있다.
orphanRemoval 은 CascadeType.REMOVE 도 가지고 있고, @ManyToOne 에서는 지원하지 않는다.
그리고 이 둘은 정말 숙고하고 사용해야 한다..
아마 예전에 11월 24일 금요일 TIL 이었나? 비밀번호 수정이 되지 않은 건 이것 때문이 아니었을까..???
반응형