2009-07-16 8 views
35

En JPA, ¿hay alguna manera se puede replicar de hibernación de saveOrUpdate behavior,¿Cómo se puede replicar SaveOrUpdate de Hibernate en JPA?

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) 

que esencialmente comprueba si el objeto ya existe en la base de datos y, o bien cambios que se oponen como necesario o guarda una nueva instancia de la objeto.

Las lecturas de JPA sin traducción son agradables, pero realmente me falta este método de Hibernate. ¿Cómo manejan esto los desarrolladores experimentados de JPA?

+0

¿Qué pasa si comprueba si la "clave principal" es nula? –

Respuesta

27

Pruebe usar el método EntityManager.merge - esto es muy similar.

Hay una excelente descripción de las diferencias en el blogpost de Xebia: "JPA Implementation Patterns: Saving (Detached) Entities".

+6

Lo más importante para mí aquí es "Al actualizar una entidad existente, no invocamos ningún método EntityManager; el proveedor JPA actualizará automáticamente la base de datos al momento del vaciado o de compromiso". –

+1

El enlace está muerto. Aquí está el nuevo: http://blog.xebia.com/jpa-implementation-patterns-saving-detached-entities/ – Dmitry

5

El problema con el método descrito en el artículo al que Pablojim se vinculó es que no maneja muy bien las claves primarias generadas automáticamente. Considere la creación de un nuevo objeto de entidad ORM, puede proporcionarle los mismos datos que una fila existente la misma clave principal, que en una entidad que utiliza claves generadas automáticamente, no puede obtener hasta que vaya a la base de datos.

Aquí está mi trabajo actual para esa situación;

/** 
* 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()); 
    } 
} 
+1

merge y saveOrUpdate son superficialmente similares, pero no son lo mismo. La semántica tiene diferencias importantes. – skaffman

+0

@skaffman, ¿crees que mi enfoque es defectuoso? Podrías lanzar algunas críticas constructivas a mi manera si es así. Soy un bebé en el bosque para este material de JPA. –

+0

Acabo de encontrar este hilo antiguo, y estoy implementando algo así como esta solución, excepto con el nuevo Java ENUMS. Gracias. – oberger

Cuestiones relacionadas