[jpa] JPA EntityManager: Why use persist() over merge()?

If you're using the assigned generator, using merge instead of persist can cause a redundant SQL statement, therefore affecting performance.

Also, calling merge for managed entities is also a mistake since managed entities are automatically managed by Hibernate, and their state is synchronized with the database record by the dirty checking mechanism upon flushing the Persistence Context.

To understand how all this works, you should first know that Hibernate shifts the developer mindset from SQL statements to entity state transitions.

Once an entity is actively managed by Hibernate, all changes are going to be automatically propagated to the database.

Hibernate monitors currently attached entities. But for an entity to become managed, it must be in the right entity state.

To understand the JPA state transitions better, you can visualize the following diagram:

JPA entity state transitions

Or if you use the Hibernate specific API:

Hibernate entity state transitions

As illustrated by the above diagrams, an entity can be in one of the following four states:

  • New (Transient)

A newly created object that hasn’t ever been associated with a Hibernate Session (a.k.a Persistence Context) and is not mapped to any database table row is considered to be in the New (Transient) state.

To become persisted we need to either explicitly call the EntityManager#persist method or make use of the transitive persistence mechanism.

  • Persistent (Managed)

    A persistent entity has been associated with a database table row and it’s being managed by the currently running Persistence Context. Any change made to such an entity is going to be detected and propagated to the database (during the Session flush-time). With Hibernate, we no longer have to execute INSERT/UPDATE/DELETE statements. Hibernate employs a transactional write-behind working style and changes are synchronized at the very last responsible moment, during the current Session flush-time.

  • Detached

Once the currently running Persistence Context is closed all the previously managed entities become detached. Successive changes will no longer be tracked and no automatic database synchronization is going to happen.

To associate a detached entity to an active Hibernate Session, you can choose one of the following options:

  • Reattaching

    Hibernate (but not JPA 2.1) supports reattaching through the Session#update method.

    A Hibernate Session can only associate one Entity object for a given database row. This is because the Persistence Context acts as an in-memory cache (first level cache) and only one value (entity) is associated with a given key (entity type and database identifier).

    An entity can be reattached only if there is no other JVM object (matching the same database row) already associated with the current Hibernate Session.

  • Merging

    The merge is going to copy the detached entity state (source) to a managed entity instance (destination). If the merging entity has no equivalent in the current Session, one will be fetched from the database.

    The detached object instance will continue to remain detached even after the merge operation.

  • Remove

    Although JPA demands that managed entities only are allowed to be removed, Hibernate can also delete detached entities (but only through a Session#delete method call).

    A removed entity is only scheduled for deletion and the actual database DELETE statement will be executed during Session flush-time.

Examples related to jpa

No converter found capable of converting from type to type How does spring.jpa.hibernate.ddl-auto property exactly work in Spring? Deserialize Java 8 LocalDateTime with JacksonMapper Error creating bean with name 'entityManagerFactory' defined in class path resource : Invocation of init method failed How to beautifully update a JPA entity in Spring Data? JPA Hibernate Persistence exception [PersistenceUnit: default] Unable to build Hibernate SessionFactory How to return a custom object from a Spring Data JPA GROUP BY query How to find distinct rows with field in list using JPA and Spring? What is this spring.jpa.open-in-view=true property in Spring Boot? Spring Data JPA and Exists query

Examples related to merge

Pandas Merging 101 Python: pandas merge multiple dataframes Git merge with force overwrite Merge two dataframes by index Visual Studio Code how to resolve merge conflicts with git? merge one local branch into another local branch Merging dataframes on index with pandas Git merge is not possible because I have unmerged files Git merge develop into feature branch outputs "Already up-to-date" while it's not How merge two objects array in angularjs?

Examples related to entitymanager

What does EntityManager.flush do and why do I need to use it? JPA With Hibernate Error: [PersistenceUnit: JPA] Unable to build EntityManagerFactory The EntityManager is closed What is the best way to update the entity in JPA Create JPA EntityManager without persistence.xml configuration file JPA EntityManager: Why use persist() over merge()?

Examples related to persist

PersistentObjectException: detached entity passed to persist thrown by JPA and Hibernate JPA EntityManager: Why use persist() over merge()?

Examples related to java-persistence-api

Difference between FetchType LAZY and EAGER in Java Persistence API? JPA EntityManager: Why use persist() over merge()?