2011-11-08 32 views
21

Estoy utilizando la anotación @Configuration para la configuración del archivo de primavera en lugar del archivo xml. Estoy configurando 2 fuentes de datos con una fábrica de sesiones diferente y diferentes administradores de transacciones. Estoy atascado con un problema aquí para la anotación @EnableTransactionManagement. He leído en su documentación que,anotación @EnableTransactionManagement con 2 gestores de transacciones

@EnableTransactionManagement is more flexible; it will fall back to a by-type lookup for any PlatformTransactionManager bean in the container. Thus the name can be "txManager", "transactionManager", or "tm": it simply does not matter.

Esto significa que cualquiera que sea el nombre que doy a método, siempre va a buscar el método que devuelve PlatformTransactionManager objeto mientras tengo 2 transactionmanagers. Ahora el problema es, cuando pruebo esta clase, me da error:

org.springframework.beans.factory.NoSuchBeanDefinitionException : No unique bean of type [ org.springframework.transaction.PlatformTransactionManager ] is defined: expected single bean but found 2

incluso traté de tener 2 clases de configuración diferentes, pero en vano. En la configuración xml, este no era el caso. Registré a mis dos gerentes 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 deseo configurar 2 orígenes de datos con 2 gestores de transacciones diferentes en la clase de configuración anotada de Spring?

+0

Esto puede ser un error, ya que Spring 3.1 todavía está en la etapa beta/rc. – skaffman

Respuesta

5

Desde el java doc

For those that wish to establish a more direct relationship between
@EnableTransactionManagement and the exact transaction manager bean to be used, the TransactionManagementConfigurer callback interface may be implemented - notice the implements clause and the @Override -annotated method below:

Su clase @Configuration debe implementar la interfaz TransactionManagementConfigurer - implementar el annotationDrivenTransactionManager que devolverá la referencia al transactionManager que se debe utilizar.

+0

También había leído esto. Pero el problema aquí es que el método implementado llama al método transactionmanager y devuelve el mismo objeto de administrador de transacciones, mientras que yo quiero tener 2 gestores de transacciones en mi clase de configuración. Y como @EnableTransactionManagement no ve el nombre del método, solo aparece para ver cuál es el objeto PlatformTransactionManagement, no permitirá 2 gestores de transacciones en la configuración. –

+0

simplemente devuelva la referencia a la que desea utilizar por @EnableTransactionManagement desde el método annotationDrivenTransactionManager – gkamal

+0

Ahí es donde está el problema. No se ha solucionado qué gestor de transacciones se utilizará, ya que depende del objeto modelo. Tengo 2 modelos de 2 bases de datos diferentes, pero las entradas se hacen al mismo tiempo en ambos. Ahora, si de todos modos, los datos no se pueden insertar en 1 tabla, la otra entrada también se debe descartar y, por lo tanto, la reversión de la transacción puede ocurrir en cualquier lugar. –

1

No estoy seguro de por qué está utilizando dos Asistentes de Transacción. Podría considerar usar el mismo TransactionManager para múltiples fuentes de datos a través de AbstractRoutingDataSource. Por favor refiérase

http://blog.springsource.org/2007/01/23/dynamic-datasource-routing/

para una muestra de su uso.

+0

DB y JMS de TransactionManager separados, por ejemplo. – teknopaul

0

Algunas de las otras respuestas implican que el uso de dos gestores de transacciones es, de alguna manera, incorrecto; sin embargo, la configuración XML de Spring permite el uso de múltiples gestores 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 administrador de transacciones opcional.

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

Most Spring applications only need a single transaction manager, but there may be situations where you want multiple independent transaction managers in a single application. The value attribute of the @Transactional annotation can be used to optionally specify the identity of the PlatformTransactionManager to be used. This can either be the bean name or the qualifier value of the transaction manager bean. For example, using the qualifier notation, the following Java code

25

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

definir 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; 
    } 

de ahí, en tu clase/método que se ejecuta el trabajo transaccional (s), anotar la siguiente manera:

@Transactional("txName") 

o

@Transactional(value = "txName") 

Así es como vincularía un gestor de transacciones calificado por nombre a donde lo necesite. Ahora puede tener tantos administradores de transacciones como desee y usarlos en consecuencia donde lo necesite.

+0

¡Genial! ¡¡Funciona!! – jherranzm

+0

¡Me ahorró varias horas! Gracias –

7

Sólo en caso de que alguien se encuentra con este problema, he encontrado 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, se puede utilizar un txManager específico definido en una configuración XML.

En caso de que quiera definir el txManager utilizarse con el servicio de nivel, deberá eliminar la @EnableTransactionManagement anotación de la clase @Configuration y especifique la txManager en los @Transactional anotaciones, por ejemplo,

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

¿Cómo fue compatible con dos gestores de transacciones? – instanceOfObject

+0

Puede configurar tantos 'txManager's como desee en XML, y puede usar cualquiera de los' 'txManager's configurados en aplicaciones o nivel de servicio usando la anotación' @DependsOn() 'o' @Transactional() ' descrito arriba – Sleeper9

Cuestiones relacionadas