web-dev-qa-db-fra.com

Comment pouvez-vous répliquer saveOrUpdate d'Hibernate dans JPA?

Dans JPA, existe-t-il un moyen de répliquer Hibernate comportement saveOrUpdate ,

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)

qui vérifie essentiellement si l'objet existe déjà dans la base de données et met à jour cet objet au besoin ou enregistre une nouvelle instance de l'objet.

Les lectures sans transcation JPA sont agréables, mais cette méthode me manque vraiment dans Hibernate. Comment les développeurs JPA expérimentés gèrent-ils cela?

38
James McMahon

Essayez d'utiliser le EntityManager.merge méthode - c'est très similaire.

Il y a une excellente description des différences dans le blog de Xebia: " JPA Implementation Patterns: Saving (Detached) Entities ."

29
Pablojim

Le problème avec la méthode décrite dans l'article auquel Pablojim a lié, c'est qu'elle ne gère pas très bien les clés primaires générées automatiquement.

Envisagez la création d'un nouvel objet d'entité ORM, vous pouvez lui donner les mêmes données qu'une ligne existante dans la table de base de données, mais sauf erreur, le gestionnaire d'entités ne les reconnaît pas comme la même ligne jusqu'à ce qu'ils aient la même clé primaire , que dans une entité qui utilise des clés générées automatiquement, vous ne pouvez pas obtenir jusqu'à ce que vous montiez à la base de données.

Voici mon travail actuel autour de cette 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());
    }
}
4
James McMahon