为何已有session.evict()仍需EntityManager.detach()?四类方法差异解析
Great question—this is a super common point of confusion when working with Hibernate and JPA, since there's overlap between native Hibernate APIs and standard JPA methods. Let's break this down step by step:
First off, let's get this straight: these two methods do exactly the same thing—they remove an entity from the persistence context (Hibernate's Session or JPA's EntityManager), turning the entity into a detached state.
The only difference is their origin:
session.evict()is a native Hibernate method, part of Hibernate's ownSessionAPI.EntityManager.detach()is defined by the JPA specification, which all JPA providers (like Hibernate, EclipseLink) must implement.
So why use one over the other? If you're writing code that needs to be portable across different JPA implementations (say, switching from Hibernate to EclipseLink later), stick with detach(). If your project is strictly Hibernate-only, evict() works just fine—no functional difference here.
Now, these are in a completely different category than evict()/detach(). While evict/detach just cut the entity's link to the persistence context, remove() and delete() delete the entity from the database.
Again, we're looking at JPA standard vs Hibernate native:
EntityManager.remove()is the JPA-standard way to mark a persistent entity (one currently tracked by the EntityManager) for deletion. When the transaction commits (or you callflush()), aDELETESQL statement is sent to the database to remove the corresponding record.Session.delete()is Hibernate's native equivalent. It does the same core job, but has a small extension: Hibernate lets you pass a detached entity (as long as it has a valid primary key) todelete(), whereas strict JPA requiresremove()to be called on a persistent entity. That said, Hibernate's implementation ofremove()also supports this extension, so it's a minor distinction.
Let's wrap up with a clear comparison of each method's purpose and behavior:
session.evict(Object entity) (Hibernate Native)
- What it does: Removes a persistent entity from the Hibernate Session, making it detached. The Session stops tracking any changes to this entity.
- Database impact: None. The entity's record still exists in the database.
- Use case: Free up Session cache space, or prevent accidental updates to an entity you don't want to sync to the DB right now.
EntityManager.detach(Object entity) (JPA Standard)
- What it does: Identical to
evict()—just the JPA-spec version of the same functionality. - Database impact: None.
- Use case: Write portable JPA code that works across any JPA provider.
EntityManager.remove(Object entity) (JPA Standard)
- What it does: Marks a persistent entity for deletion. The DB record is deleted when the transaction commits or
flush()is called. - Database impact: Deletes the corresponding record.
- Use case: Standard JPA entity deletion in portable code.
Session.delete(Object entity) (Hibernate Native)
- What it does: Same core deletion logic as
remove(), but with Hibernate's flexibility to accept detached entities (as long as they have a valid ID). - Database impact: Deletes the corresponding record.
- Use case: Hibernate-specific projects, or when you need to delete a detached entity without first reattaching it.
内容的提问来源于stack exchange,提问作者Ninad Gosavi

