Pregunta Spring @Transactional fusionar y persistir pregunta


nuevo en Spring y aquí @stackoverflow

Estoy construyendo una aplicación independiente de seguimiento de inventario y ventas (Apache Pivot / Spring / JPA / Hibernate / MySQL) para un negocio de distribución.

Hasta ahora, creo que todo es CRUD, así que planeo tener una clase base con todo @Transactional.

Luego tuve un problema con mi método genérico de guardar. ¿El método de persistencia y fusión del EntityManager de Spring tiene alguna diferencia?

Intenté correr y llamé guardar para insertar y actualizar, y funcionó bien (creo que Spring actualiza automáticamente la entidad cada vez que llamo a mi método de guardar // vi las consultas de hibernación que se estaban registrando, ¿verdad?).

@Transactional
public abstract class GenericDAO {

    protected EntityManager em;

//  em getter+@PersistenceContext/setter

    public void save(T t) {
//        if (t.getId() == null) // create new
//        {
//            em.persist(t);
//        } else // update
//        {
            em.merge(t);
//        }
    }
}

Y, por cierto, teniendo una configuración como esta, no voy a comprometer el rendimiento mucho, ¿verdad? Como llamar a salesDAO.findAll () para generar informes (que no es necesario que sean transaccionales, ¿no?).

¡¡¡Gracias!!!


5
2017-10-18 04:06


origen


Respuestas:


Esta pregunta SO es una buena discusión de persistir contra fusionar, y la respuesta aceptada lo explica bastante bien. La otra respuesta también vincula a una buena publicación de blog sobre esto.

Según la primera respuesta en esta otra publicación, parece que sería posible fusionar para guardar y actualizar una entidad, pero no es así como lo hice. En mis aplicaciones Spring / JPA, solo hago que mis DAO amplíen JpaDaoSupport y utilicen getJpaTemplate () de la siguiente manera.

/**
 * Save a new Album.
 */
public Album save(Album album) {
    getJpaTemplate().persist(album);
    return album;
}

/**
 * Update an existing Album.
 */
public Album update(Album album) {
    return getJpaTemplate().merge(album);
}

5
2017-10-18 14:37



los enlazar a la otra pregunta de SO que Kaleb publicó hace un buen trabajo al cubrir las diferencias y los errores de persist () vs merge (). Sin embargo, siempre he implementado mis clases de Dao con un método save () que solo llama a merge () para manejar tanto inserciones como actualizaciones, y nunca me he topado con ninguno de los errores persistentes () vs merge ().

En cuanto a rendimiento y métodos transaccionales: Utilizando @Transactional en los métodos que solo son operaciones de lectura no afectarán el rendimiento, aunque prefiero usar las anotaciones en el nivel de método solo para poder decir fácilmente qué métodos son actualizaciones y cuáles son lecturas. Puede hacer esto configurando el readOnly atributo en el @Transactional anotación.

Si sigue una convención de nomenclatura en sus métodos (es decir, cualquier método de lectura siempre comienza con getXXX), también podría usar la sintaxis de Poincut en su archivo de configuración Spring para hacer automáticamente esta diferenciación:

  <tx:advice id="txAdvice" transaction-manager="txManager">
    <tx:attributes>
      <tx:method name="get*" read-only="true"/>
      <tx:method name="*"/>
    </tx:attributes>
  </tx:advice>

Ver el Documentación de primavera sobre transacciones. para más información.

Además, normalmente pongo el @Transactional atribuye un nivel por encima de mis clases Dao, en una capa de servicio. Los métodos en las clases de Dao son entonces operaciones de base de datos distintas para cada llamada de método, mientras que los métodos de servicio pueden realizar una única confirmación / retrotracción para una serie de actualizaciones.


4
2017-10-18 15:49