Anotación @Transactional. Cómo revertir?

Utilicé esta anotación con éxito para una clase Dao. Y el retroceso funciona para las pruebas.

Pero ahora necesito revertir el código real, no solo las pruebas. Hay anotaciones especiales para usar en las pruebas. ¿Pero qué anotaciones son para código que no es de prueba? Es una gran pregunta para mí. Pasé un día para eso ya. La documentación oficial no satisfizo mis necesidades.

class MyClass { // this does not make rollback! And record appears in DB. EmployeeDaoInterface employeeDao; public MyClass() { ApplicationContext context = new ClassPathXmlApplicationContext( new String[] { "HibernateDaoBeans.xml" }); employeeDao = (IEmployeeDao) context.getBean("employeeDao"); } @Transactional(rollbackFor={Exception.class}) public void doInsert( Employee newEmp ) throws Exception { employeeDao.insertEmployee(newEmp); throw new RuntimeException(); } } 

employeeDao es

 @Transactional public class EmployeeDao implements IEmployeeDao { private SessionFactory sessionFactory; public void setSessionFactory(SessionFactory sessionFactory) { this.sessionFactory = sessionFactory; } public void insertEmployee(Employee emp) { sessionFactory.getCurrentSession().save(emp); } } 

Y aquí hay una prueba para la cual las anotaciones funcionan bien:

 @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = { "/HibernateDaoBeans.xml" }) @TransactionConfiguration(transactionManager = "txManager", defaultRollback = true) @Transactional public class EmployeeDaoTest { @Autowired EmployeeDaoInterface empDao; @Test public void insert_record() { ... assertTrue(empDao.insertEmployee(newEmp)); } 

HibernateDaoBeans.xml

  ...        ... 



** SÍ, revertí la transacción. Acabo de agregar BEAN para el servicio … y luego la anotación @Transactional comienza a funcionar 🙂 **

    

¡Gracias a todos, Rusia no te olvidará!

Simplemente arroje cualquier RuntimeException de un método marcado como @Transactional .

Por defecto, todas las transacciones de reversión de RuntimeException , mientras que las excepciones marcadas no. Este es un legado de EJB. Puede configurar esto utilizando los parámetros de anotación rollbackFor() y noRollbackFor() :

 @Transactional(rollbackFor=Exception.class) 

Esto revertirá la transacción después de lanzar cualquier excepción.

o programáticamente

 TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); 

Puede lanzar una excepción sin marcar desde el método que desea revertir. Esto se detectará antes de la spring y su transacción se marcará como reversión solamente.

Supongo que estás usando Spring aquí. Y asumo que las anotaciones a las que se refiere en sus pruebas son las anotaciones basadas en la prueba de spring.

La forma recomendada de indicar a la infraestructura de transacciones de Spring Framework que el trabajo de una transacción se va a retrotraer es arrojar una excepción del código que se está ejecutando actualmente en el contexto de una transacción.

y tenga en cuenta que:

tenga en cuenta que el código de infraestructura de transacciones de Spring Framework, de forma predeterminada, solo marcará una transacción para reversión en el caso del tiempo de ejecución, excepciones no verificadas; es decir, cuando la excepción lanzada es una instancia o subclase de RuntimeException.

Si desea crear un método Rollback () en su API, puede haber una forma. Crea un nuevo método ().

 @Component public class MyDBApiImpl implements MyDBApi{ @Autowired private DummyExceptionLauncher dummyExceptionLauncher; @Override @Transactional(propagation=Propagation.MANDATORY) public void rollback(){ try{ dummyExceptionLauncher.throwException(); }catch(RuntimeException ex){ log.debug("Transaction deliberately aborted"); } } } 

Dónde

 @Component public class DummyExceptionLauncherImpl implements DummyExceptionLauncher{ @Override @Transactional(propagation=Propagation.MANDATORY) public void throwException(){ throw new RuntimeException("Exception deliberated thrown to abort exception"); } } 

Tenga en cuenta que es posible que deba atrapar excepciones de retrotracción “Transacción marcada como rollbackOnly”.

Para mí, la reversión no fue suficiente, así que tuve que poner esto y funciona como esperaba:

 @Transactional(propagation = Propagation.REQUIRED, readOnly = false, rollbackFor = Exception.class) 

Espero que ayude 🙂