JPA EntityManager: Why use persist() over merge()?

后端 未结 15 1431
说谎
说谎 2020-11-22 03:09

EntityManager.merge() can insert new objects and update existing ones.

Why would one want to use persist() (which can only create new objec

15条回答
  •  小蘑菇
    小蘑菇 (楼主)
    2020-11-22 03:25

    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.

    • Removed

      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.

提交回复
热议问题