1. 테스트코드
(생략)
tx.begin();
Member member3 = new Member();
member.setName("sun");
member.setTeam(team);
em.persist(member3);
em.flush();
em.clear();
em.remove(member3);
tx.commit();
(생략)
2. 결과
java.lang.IllegalArgumentException: Removing a detached instance org.Entity.Member#3
at org.hibernate.event.internal.DefaultDeleteEventListener.disallowDeletionOfDetached(DefaultDeleteEventListener.java:196)
at org.hibernate.event.internal.DefaultDeleteEventListener.performDetachedEntityDeletionCheck(DefaultDeleteEventListener.java:184)
at org.hibernate.event.internal.DefaultDeleteEventListener.onDelete(DefaultDeleteEventListener.java:105)
at org.hibernate.event.internal.DefaultDeleteEventListener.onDelete(DefaultDeleteEventListener.java:72)
at org.hibernate.internal.SessionImpl.fireDelete(SessionImpl.java:1011)
at org.hibernate.internal.SessionImpl.delete(SessionImpl.java:947)
at org.hibernate.internal.SessionImpl.remove(SessionImpl.java:3441)
at org.example.Main.main(Main.java:170)
- JPA remove를 사용할 때는반드시 영속 상태의 entity를 대상으로 해야 한다.
-> 따라서 entity를 찾지 않은 상태에서 delete만 하고 싶은 경우라면 entity를 찾아와야 하는 비효율이 발생한다.
- 실제로
SimpleJpaRepository
에서도 아래와 같이 구현하고 있다.
@Override
@Transactional
@SuppressWarnings("unchecked")
public void delete(T entity) {
Assert.notNull(entity, "Entity must not be null");
if (entityInformation.isNew(entity)) {
return;
}
Class<?> type = ProxyUtils.getUserClass(entity);
T existing = (T) em.find(type, entityInformation.getId(entity));
if (existing == null) {
return;
}
em.remove(em.contains(entity) ? entity : em.merge(entity));
}
- entity를 찾지 않고 delete를 바로 하고 싶은 경우에는 JPQL을 써야 한다.