Estoy escribiendo una aplicación simple (Spring + Hibernate + PostgreSql db). Solo intento construir un objeto de muestra y persistir en db.Transacción de muelles - reversión automática de actualizaciones de db anteriores cuando una actualización db falla
corro un método main de la clase Java simple donde he cargado el applicationContext y tengo referencia a la clase de servicio de la siguiente manera Contexto
TestService srv = (TestService)factory.getBean("testService");
Aplicación - contexto:
<bean id="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactoryVsm" />
</bean>
<bean id="testService" class="com.test.service.TestServiceImpl">
<property name="testDao" ref="testDao"/>
</bean>
<bean id="testDao" class="com.test.dao.TestDaoImpl>
<property name="sessionFactory" ref="sessionFactoryVsm"/>
</bean>
En TestService, he inyectado TestDao. En el método de servicio de prueba, he construido objetos para empleados emp1 y emp2 y llamo a dao dos veces para actualizar.
código TestDaoImpl:
public void saveOrUpdate(BaseDomainModel baseObject) {
Session session = null;
try {
session = getHibernateTemplate().getSessionFactory().openSession();
session.saveOrUpdate(baseObject);
session.flush();
} catch (Exception e) {
logger.error("Generic DAO:saveOrUpdate::" + e);
e.printStackTrace();
} finally {
if (session != null) {
session.close();
}
}
}
Cuando falla la actualización EMP2 EMP1 también debe fallar. Cómo puedo hacer eso. Por favor, asesoramiento
Gracias de antemano
Actualizado:
Gracias Nanda. Intenté una transacción declarativa. Pero no está funcionando. Emp1 persiste y no retrocede eveb. La segunda llamada dao falla. He agregado asesoramiento de transacción al método.
para probar si se aplica o no el consejo de la operación i cambiado la propagación de "NOT_SUPPORTED". pero aún emp1 persiste. la expectativa es que deberíamos tener el tipo de excepción de Transaction Not Supported. por favor aconséjame .
ACTUALIZADO
@seanizer - Gracias por la actualización. Incluso intenté agregar
@Transactional (propagation = Propagation.NOT_SUPPORTED) public void saveEmp (Employee emp) a ese método de servicio. Pero no funcionó. Además, repetir la retención de la colección solo es bueno si necesito llamar a un dao. Si en caso de tener que llamar a dos dao diferentes para persistir obj1 y obj2, esto puede no ser de ayuda. Solo para verificar si la transacción se está aplicando obtengo @Transactional (propagation = Propagation.NOT_SUPPORTED). Pero todavía obj1 persistió. Sólo dudo si la configuración xml/anotación dada es correcta. compruebe
<bean id="txManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactoryVsm" />
</bean>
<tx:advice id="txAdvice" transaction-manager="txManager">
<tx:attributes>
<tx:method name="saveEmp" propagation="REQUIRED" rollback-for="Exception"/>
<tx:method name="*"/>
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut id="testServiceOperation" expression="execution(*com.test.service.*(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="testServiceOperation"/>
</aop:config>
estoy usando org.springframework.orm.hibernate3.HibernateTransactionManager para la transactionManager. Es esto correcto ?
Actualizado
He creado mi clase de excepción que se extiende desde myRuntimeExp RuntimeException y lanzando el mismo método de Dao con el método de servicio. pero aún así la reversión no está sucediendo.Dudo que haya dado correctamente las configuraciones en el applnContext.xml. ¿Alguien puede ayudarme a verificar si el asesoramiento/anotación de la transacción se está aplicando al método o no? ¿hay alguna manera de funcionar en un modo de depuración y comprobar
Edición:
que estaba usando
session = getHibernateTemplate().getSessionFactory().openSession();
Sin embargo, cabe sesión actual y se está trabajando muy bien.
session = getHibernateTemplate().getSessionFactory().getCurrentSession();
¿Sirve Spring Declarative Transaction en este caso? – Vaandu
sí, por supuesto, declare que la transacción es necesaria en el momento Y en el nivel de servicio. Si el dao detecta que el servicio ha abierto la transacción, usará esto en lugar de crear una nueva transacción. – nanda
No estoy de acuerdo, las transacciones deberían ser necesarias en los métodos de servicio, no en los métodos de dao. De esta forma, una llamada de servicio puede ser atómica incluso si usa múltiples métodos de dao (sí, sé que también puede lograrlo uniendo las transacciones existentes, pero prefiero una separación limpia de capas) –