2011-11-08 6 views
21

Używam adnotacji @Configuration do konfiguracji pliku sprężyny zamiast xml. Konfiguruję 2 źródła danych z różnymi fabrykami sesji i różnymi menedżerami transakcji. Utknąłem z problemem tutaj dla adnotacji @EnableTransactionManagement. Czytałam w jego dokumentacji,@EnableTransactionManagement adnotacja z 2 menedżerami transakcji

@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.

Oznacza to cokolwiek nazwa daję metody, zawsze będzie szukać sposobu, który powraca PlatformTransactionManager obiekt natomiast mam 2 transactionmanagers. Problem polega na tym, że kiedy testuję tę klasę, daje mi to błąd:

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

Próbowałem nawet 2 różnych klas konfiguracji, ale na próżno. W konfiguracji xml tak nie było. Zarejestrowałem oba menedżery transakcji z dwoma tagami <tx:annotation-driven transaction-manager="" /> i wszystko działało bez zarzutu. Ale nie można tego zrobić tutaj z adnotacjami.

Co należy zrobić, jeśli chcę skonfigurować 2 źródła danych z 2 różnymi menedżerami transakcji w klasie konfiguracji z adnotacjami Spring?

+0

To może być błąd, ponieważ Spring 3.1 jest wciąż w wersji beta/rc. – skaffman

Odpowiedz

5

Z 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:

klasie @Configuration musi wdrożyć TransactionManagementConfigurer interfejs - Wdrożenie annotationDrivenTransactionManager która zwróci referencję do transactionManager które powinny być stosowane.

+0

Przeczytałem to również. Ale problem polega na tym, że zaimplementowana metoda wywołuje metodę transactionmanager i zwraca ten sam obiekt menedżera transakcji, podczas gdy chcę mieć 2 menedżerów transakcji w mojej klasie konfiguracji. A ponieważ @EnableTransactionManagement nie widzi nazwy metody, po prostu upada, aby zobaczyć, który obiekt PlatformTransactionManagement, nie pozwoli na 2 menedżerów transakcji w konfiguracji. –

+0

po prostu zwróć odwołanie do tego, którego chcesz użyć @EnableTransactionManagement z metody adnotationDrivenTransactionManager. – gkamal

+0

To jest problem. Nie ustalono, który menedżer transakcji będzie używany, ponieważ zależy on od obiektu modelu. Mam 2 modele z 2 różnych baz danych, ale wpisy są wykonywane w tym samym czasie w obu z nich. Teraz, jeśli w ogóle, danych nie można wstawić do jednej tabeli, druga pozycja również powinna zostać odrzucona, a zatem wycofanie transakcji może nastąpić w dowolnym miejscu. –

1

Nie jestem pewien, dlaczego używasz dwóch menedżerów transakcji. Można rozważyć użycie tego samego menedżera TransactionManager dla wielu źródeł danych za pośrednictwem obiektu AbstractRoutingDataSource. Proszę odnieść

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

dla próbki z jego użytkowania.

+0

Na przykład oddzielne transakcje DB i JMS TransactionManager. – teknopaul

0

Niektóre inne odpowiedzi sugerują, że używanie dwóch menedżerów transakcji jest w jakiś sposób nieprawidłowe; jednak konfiguracja XML Springa pozwala na korzystanie z wielu menedżerów transakcji, zgodnie z dokumentacją online (poniżej). Niestety, nie ma sposobu, aby dokonać adnotacji @EnableTransactionManagement w podobny sposób. W rezultacie po prostu używam adnotacji @ImportResource, aby załadować plik XML, który zawiera linię <tx:annotation-driven/>. Pozwala to uzyskać konfigurację Java dla większości rzeczy, ale nadal korzysta z @Transactional z opcjonalnym kwalifikatorem Transaction Manager.

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

W swojej klasie konfiguracji, użyj @EnableTransactionManagement adnotacji.

Definiowanie menedżera transakcji w tej klasie jak:

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

tam, w swojej klasie/metody, która wykonuje pracę transakcyjnej (e), opisywanie następująco:

@Transactional("txName") 

lub

@Transactional(value = "txName") 

W ten sposób zawiążesz kwalifikowanego menedżera transakcji w dowolnym miejscu. Możesz teraz mieć tylu menedżerów transakcji, ile chcesz i używać ich odpowiednio, gdziekolwiek potrzebujesz.

+0

Świetnie! To działa!! – jherranzm

+0

Zaoszczędził mi kilka godzin! Dzięki –

7

wszelki wypadek ktoś wpada na ten problem, znalazłem rozwiązanie:

@Configuration 
@EnableTransactionManagement 
@DependsOn("myTxManager") 
@ImportResource("classpath:applicationContext.xml") 
public class AppConfig implements TransactionManagementConfigurer { 

@Autowired 
private PlatformTransactionManager myTxManager; 

... 

@Override 
public PlatformTransactionManager annotationDrivenTransactionManager() { 
    return this.myTxManager; 
} 

w ten sposób, można użyć konkretnego txManager zdefiniowany w konfiguracji xml.

W przypadku, gdy chcesz zdefiniować txManager używany na poziomie usług, będziecie usunąć z @EnableTransactionManagement adnotacji z klasy @Configuration i określ txManager w @Transactional adnotacji, np

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

W jaki sposób obsługuje dwóch menedżerów transakcji? – instanceOfObject

+0

Możesz skonfigurować dowolną liczbę 'txManager'ów w XML i możesz użyć dowolnego skonfigurowanego' txManager' na aplikacjach lub poziomie usług, używając adnotacji '@DependsOn()' lub '@Transactional()' opisane powyżej – Sleeper9

Powiązane problemy