transaction jpatransactionmanager example driven data annotation java spring spring-3 spring-annotations

java - jpatransactionmanager - @EnableTransactionManagement anotación con 2 gestores de transacciones



transactionmanager spring 4 (6)

Estoy usando la anotación @Configuration para la configuración de spring en lugar de un archivo xml. Estoy configurando 2 fuentes de datos con diferentes sesiones de fábrica y diferentes gestores de transacciones. Estoy atascado con un problema aquí para la anotación @EnableTransactionManagement . Leí en su documentación que,

@EnableTransactionManagement es más flexible; volverá a una búsqueda por tipo para cualquier bean PlatformTransactionManager en el contenedor. Por lo tanto, el nombre puede ser "txManager", "transactionManager" o "tm": simplemente no importa.

Esto significa que cualquiera sea el nombre que le dé al método, siempre buscará el método que devuelve el objeto PlatformTransactionManager mientras tengo 2 gestores de transacciones. Ahora el problema es que cuando pruebo esta clase, me da un error:

org.springframework.beans.factory.NoSuchBeanDefinitionException : No se org.springframework.beans.factory.NoSuchBeanDefinitionException ningún bean único de tipo [ org.springframework.transaction.PlatformTransactionManager ]: se espera un solo bean pero se encuentra 2

Incluso intenté tener 2 clases de configuración diferentes pero en vano. En la configuración xml, este no fue el caso. Registré mis dos gestores de transacciones con dos etiquetas <tx:annotation-driven transaction-manager="" /> y funcionó bien. Pero no puedo hacer lo mismo aquí con anotaciones.

¿Qué debo hacer si quiero configurar 2 fuentes de datos con 2 administradores de transacciones diferentes en la clase de configuración anotada Spring?


Algunas de las otras respuestas implican que el uso de dos administradores de transacciones está mal de alguna manera; sin embargo, la configuración XML de Spring permite usar múltiples administradores de transacciones como se indica en la documentación en línea (a continuación). Desafortunadamente, no parece haber una manera de hacer que la anotación @EnableTransactionManagement funcione de manera similar. Como resultado, simplemente uso una anotación @ImportResource para cargar un archivo XML que incluye la línea <tx:annotation-driven/> . Esto le permite obtener una configuración de Java para la mayoría de las cosas pero aún así hacer uso de @Transactional con un calificador de Transaction Manager opcional.

http://docs.spring.io/spring/docs/3.1.x/spring-framework-reference/html/transaction.html

La mayoría de las aplicaciones Spring solo necesitan un solo administrador de transacciones, pero puede haber situaciones en las que desee tener múltiples administradores de transacciones independientes en una sola aplicación. El atributo de valor de la anotación @Transactional se puede usar para especificar opcionalmente la identidad del PlatformTransactionManager que se usará. Puede ser el nombre del bean o el valor calificador del bean del administrador de transacciones. Por ejemplo, usando la notación de calificador, el siguiente código de Java


Desde el documento java

Para aquellos que deseen establecer una relación más directa entre
@EnableTransactionManagement y el bean del administrador de transacciones exacto que se utilizará, la interfaz de devolución de llamada TransactionManagementConfigurer puede implementarse. Observe la cláusula de implementos y el método anotado @Override Override-abajo:

Su clase @Configuration necesita implementar la interfaz TransactionManagementConfigurer : implemente el annotationDrivenTransactionManager que devolverá la referencia al transactionManager que debe usarse.


En caso de que alguien se encuentre con este problema, encontré una solución:

@Configuration @EnableTransactionManagement @DependsOn("myTxManager") @ImportResource("classpath:applicationContext.xml") public class AppConfig implements TransactionManagementConfigurer { @Autowired private PlatformTransactionManager myTxManager; ... @Override public PlatformTransactionManager annotationDrivenTransactionManager() { return this.myTxManager; }

De esta manera, puede usar un txManager específico definido en una configuración xml.

En caso de que desee definir el txManager usado en el nivel de servicio, deberá eliminar la anotación @EnableTransactionManagement de la clase @Configuration y especificar el txManager en las anotaciones @Transactional , por ejemplo

@Service @Transactional(value="myTxManager", readOnly = true) public class MyServiceImpl implements MyService { ... }


En su clase de configuración, use la anotación @EnableTransactionManagement .

Defina un administrador de transacciones en esta clase como:

@Bean(name="txName") public HibernateTransactionManager txName() throws IOException{ HibernateTransactionManager txName= new HibernateTransactionManager(); txName.setSessionFactory(...); txName.setDataSource(...); return txName; }

A continuación, en su clase / método que ejecuta trabajos transaccionales, anote de la siguiente manera:

@Transactional("txName")

o

@Transactional(value = "txName")

Así es como uniría a un administrador de transacciones calificado con el nombre a donde lo necesites. Ahora puede tener tantos administradores de transacciones como desee y utilizarlos en consecuencia donde lo necesite.



Trate de usar TransactionalManager encadenado

import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.transaction.ChainedTransactionManager; import org.springframework.transaction.PlatformTransactionManager; @Configuration public class ChainedDBConfig { @Bean("chainedTransactionManager") public PlatformTransactionManager transactionManager( @Qualifier("database1TransactionManager") final PlatformTransactionManager db1PlatformTransactionManager, @Qualifier("database2TransactionManager") final PlatformTransactionManager db2PlatformTransactionManager) { return new ChainedTransactionManager(db1PlatformTransactionManager, db2PlatformTransactionManager); } }

Y coloque la siguiente anotación en su clase de servicio:

@Transactional(transactionManager = "chainedTransactionManager") public class AggregateMessagesJobIntegrationTest { ... }

También puedes usarlo dentro de las pruebas de integración:

@RunWith(SpringRunner.class) @Transactional(transactionManager = "chainedRawAndAggregatedTransactionManager") @Rollback public class ExampleIntegrationTest extends AbstractIntegrationTest { .... }

y hará una reversión para ambos administradores de transacciones DB.