La llamada de escritura / transacción se elimina en TransactionalEventListener

Estoy usando spring-boot (1.4.1) con hibernate (5.0.1.Final). Me di count de que cuando bash escribir en el db desde el controller @TransactionalEventListener la llamada simplemente se ignora. Una llamada de lectura funciona bien. Cuando digo ignorar, quiero decir que no hay escritura en el DB y no hay loggings. Incluso habilité log4jdbc y todavía no hay loggings lo que significa que no se creó ninguna session de hibernación. A partir de esto, creo que, en algún punto del arranque de spring, identificamos que es un controller de events de transacción e ignoramos una llamada de escritura.

Aquí hay un ejemplo.

 // This function is defined in a class marked with @Service @TransactionalEventListener open fun handleEnqueue(event: EnqueueEvent) { // some code to obtain encodeJobId this.uploadService.saveUploadEntity(uploadEntity, encodeJobId) } @Service @Transactional class UploadService { //.....code open fun saveUploadEntity(uploadEntity: UploadEntity, encodeJobId: String): UploadEntity { // some code return this.save(uploadEntity) } } 

Ahora si forzo una nueva Transacción anotando

 @Transactional(propagation = Propagation.REQUIRES_NEW) saveUploadEntity 

se hace una nueva transacción con connection y todo funciona bien.

  1. No me gusta que haya un silencio total en los loggings cuando esta escritura se descarta (de nuevo, las lecturas tienen éxito). ¿Hay algún error conocido?

  2. ¿Cómo habilitar el controller para iniciar una nueva transacción? Si hago Propogation.Requires_new en mi evento handleEnqueue, no funciona.

Además, habilitando log4jdbc que registra exitosamente las lecturas / escrituras, tengo las siguientes configuraciones en la spring.

Gracias

Tuve el mismo problema. Este comportamiento se menciona en realidad en la documentation de TransactionSynchronization # afterCompletion (int) a la que se hace reference en TransactionPhase.AFTER_COMMIT (que es el atributo pnetworkingeterminado TransactionPhase de @TransactionalEventListener):

La transacción ya se habrá comprometido o revertido, pero los resources transaccionales aún podrían estar activos y accesibles. Como consecuencia, cualquier código de acceso a datos activado en este punto aún "participará" en la transacción original, lo que permite realizar algunas tareas de limpieza (¡sin seguir el compromiso!), A less que explícitamente declare que necesita ejecutarse en una transacción separada. Por lo tanto: use PROPAGATION_REQUIRES_NEW para cualquier operación transaccional que se llame desde aquí.

Lamentablemente, esto parece no dejar otra opción que hacer cumplir una nueva transacción a través de Propagation.REQUIRES_NEW. El problema es que los events electorales transaccionales se implementan como sincronizaciones de transactions y, por lo tanto, se vinculan a la transacción. Cuando se cierra la transacción y se limpian sus resources, también lo hacen los oyentes. Puede haber una manera de utilizar un EntityManager personalizado que almacena events y luego los publica después de que se llamó a close ().

Tenga en count que puede usar TransactionPhase.BEFORE_COMMIT en su @TransactionalEventListener, que tendrá lugar antes de la confirmación de la transacción. Esto escribirá los cambios en la database, pero no sabrá si la transacción que está escuchando realmente se ha comprometido o está por deshacerse.