영속상태이지 않은 Entity를 remove하면 어떻게 될까?

선종우·2023년 7월 12일
0

실험실

목록 보기
4/4

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 the entity to be deleted doesn't exist, delete is a NOOP
		if (existing == null) {
			return;
		}

		em.remove(em.contains(entity) ? entity : em.merge(entity));
	}
  • entity를 찾지 않고 delete를 바로 하고 싶은 경우에는 JPQL을 써야 한다.

0개의 댓글