How can you replicate Hibernate's saveOrUpdate in JPA?

59,038

Solution 1

Try using the EntityManager.merge method - this is very similar.

There is an excellent description of the differences in Xebia's blogpost: "JPA Implementation Patterns: Saving (Detached) Entities."

Solution 2

The problem with the method outlined in the article that Pablojim linked to, is that it doesn't handle auto generated primary keys very well.

Consider the creation of a new ORM entity object, you can give this the same data as an existing row in the database table, but unless I am mistaken, the entity manager does not recognize them as the same row until they have the same primary key, which in a entity that uses auto generated keys, you can't get until you go up to the database.

Here is my current work around for that situation;

/**
 * Save an object into the database if it does not exist, else return
 * object that exists in the database.
 *
 * @param query query to find object in the database, should only return
 * one object.
 * @param entity Object to save or update.
 * @return Object in the database, whither it was prior or not.
 */
private Object saveOrUpdate(Query query, Object entity) {
    final int NO_RESULT = 0;
    final int RESULT = 1;

    //should return a list of ONE result, 
    // since the query should be finding unique objects
    List results = query.getResultList();
    switch (results.size()) {
        case NO_RESULT:
            em.persist(entity);
            return entity;
        case RESULT:
            return results.get(0);
        default:
            throw new NonUniqueResultException("Unexpected query results, " +
                    results.size());
    }
}
Share:
59,038

Related videos on Youtube

James McMahon
Author by

James McMahon

Blogging at https://dev.to/jamesmcmahon.

Updated on September 20, 2020

Comments

  • James McMahon
    James McMahon over 3 years

    In JPA, is there any way you can replicate Hibernate's saveOrUpdate behavior,

    saveOrUpdate
    
    public void saveOrUpdate(Object object)
                      throws HibernateException
    
        Either save(Object) or update(Object) the given instance, depending upon resolution of the unsaved-value checks (see the manual for discussion of unsaved-value checking).
    
        This operation cascades to associated instances if the association is mapped with cascade="save-update".
    
        Parameters:
            object - a transient or detached instance containing new or updated state 
        Throws:
            HibernateException
        See Also:
            save(Object), update(Object)
    

    which essentially checks to see if the object already exists in the database and either updates that object as need be or saves a new instance of the object.

    JPA transcationless reads are nice, but I am really missing this method from Hibernate. How do experienced JPA developers handle this?

    • Rémy
      Rémy almost 15 years
      What about checking if the "primary key" is null ?
  • James McMahon
    James McMahon almost 15 years
    The big take away for me here is "When updating an existing entity, we do not invoke any EntityManager method; the JPA provider will automatically update the database at flush or commit time."
  • skaffman
    skaffman almost 15 years
    merge and saveOrUpdate are superficially similar, but not the same. The semantics have important differences.
  • James McMahon
    James McMahon almost 15 years
    @skaffman, do you think my approach is flawed? Could you throw some constructive criticism my way if it is. I am a babe in the woods for this JPA stuff.
  • oberger
    oberger about 12 years
    Just found this old thread, and I am implementing something like this solution except with the new Java ENUMS. Thanks.
  • Dmitry
    Dmitry over 6 years
    Link is dead. Here is the new one: blog.xebia.com/…
  • Yashpal
    Yashpal over 2 years
    This page doesn't exist anymore, 404 page not found
  • emeraldjava
    emeraldjava over 2 years