@EnableTransactionManagement аннотация с двумя менеджерами транзакций
Я использую аннотацию @Configuration
для конфигурации spring вместо xml файла. Я настраиваю 2 источника данных с разными сеансами factory и разными менеджерами транзакций. Здесь я не вижу проблемы с аннотацией @EnableTransactionManagement
. Я прочитал в своей документации, что
@EnableTransactionManagement
более гибкий; он вернется к по типу поиска для любого PlatformTransactionManager
bean в контейнер. Таким образом, имя может быть "txManager", "transactionManager" или "tm": это просто не имеет значения.
Это означает, что любое имя, которое я даю методу, всегда будет искать метод, возвращающий объект PlatformTransactionManager
, в то время как у меня есть 2 менеджера транзакций. Теперь проблема в том, что когда я тестирую этот класс, это дает мне ошибку:
org.springframework.beans.factory.NoSuchBeanDefinitionException
: не определено уникальное bean типа [org.springframework.transaction.PlatformTransactionManager
]: ожидаемое одиночное bean, но найдено 2
Я даже пытался иметь 2 разных класса конфигурации, но напрасно. В xml-конфигурации это было не так. Я зарегистрировал обоих менеджеров транзакций двумя тегами <tx:annotation-driven transaction-manager="" />
, и он работал нормально. Но не в состоянии сделать то же самое здесь с аннотациями.
Что делать, если я хочу настроить 2 источника данных с двумя разными менеджерами транзакций в классе spring аннотированных конфигураций?
Ответы
Ответ 1
В вашем классе конфигурации используйте аннотацию @EnableTransactionManagement
.
Определите менеджера транзакций в этом классе как:
@Bean(name="txName")
public HibernateTransactionManager txName() throws IOException{
HibernateTransactionManager txName= new HibernateTransactionManager();
txName.setSessionFactory(...);
txName.setDataSource(...);
return txName;
}
Там, в вашем классе/методе, который выполняет транзакционные задания (ы), аннотируется следующим образом:
@Transactional("txName")
или
@Transactional(value = "txName")
Вот как вы привязывали бы имя квалифицированного менеджера транзакций туда, где вам это нужно. Теперь вы можете иметь столько менеджеров транзакций, сколько хотите, и использовать их там, где вам нужно.
Ответ 2
На всякий случай кто-нибудь столкнется с этой проблемой, я нашел решение:
@Configuration
@EnableTransactionManagement
@DependsOn("myTxManager")
@ImportResource("classpath:applicationContext.xml")
public class AppConfig implements TransactionManagementConfigurer {
@Autowired
private PlatformTransactionManager myTxManager;
...
@Override
public PlatformTransactionManager annotationDrivenTransactionManager() {
return this.myTxManager;
}
Таким образом, вы можете использовать определенный txManager, определенный в конфигурации xml.
Если вы хотите определить txManager, используемый на уровне сервиса, вы должны удалить аннотацию @EnableTransactionManagement
из класса @Configuration
и указать txManager в аннотациях @Transactional
, например
@Service
@Transactional(value="myTxManager", readOnly = true)
public class MyServiceImpl implements MyService { ... }
Ответ 3
Из java doc
Для тех, кто хочет установить более прямую связь между @EnableTransactionManagement
и точный менеджер транзакций bean, который будет использоваться, TransactionManagementConfigurer
интерфейс обратного вызова может быть реализован - обратите внимание на реализует предложение и @Override
-номененный метод ниже:
Вашему классу @Configuration
необходимо реализовать интерфейс TransactionManagementConfigurer
- реализовать annotationDrivenTransactionManager
, который вернет ссылку на transactionManager
, которая должна использоваться.
Ответ 4
Я не уверен, почему вы используете два TransactionManagers. Вы можете использовать один и тот же TransactionManager для нескольких источников данных через AbstractRoutingDataSource. Пожалуйста, обратитесь
http://blog.springsource.org/2007/01/23/dynamic-datasource-routing/
для образца по его использованию.
Ответ 5
Некоторые из других ответов подразумевают, что использование двух менеджеров транзакций в некотором роде неверно; однако конфигурация XML Spring позволяет использовать несколько менеджеров транзакций, как указано в онлайн-документации (см. ниже). К сожалению, похоже, что метод аннотации @EnableTransactionManagement
не похож. В результате я просто использую аннотацию @ImportResource
для загрузки XML файла, который включает в себя строку <tx:annotation-driven/>
. Это позволяет вам получить конфигурацию Java для большинства вещей, но при этом использовать @Transactional
с дополнительным квалификатором Transaction Manager.
http://docs.spring.io/spring/docs/3.1.x/spring-framework-reference/html/transaction.html
В большинстве приложений Spring нужен только один диспетчер транзакций, но могут быть ситуации, когда требуется несколько независимых менеджеров транзакций в одном приложении. Атрибут value аннотации @Transactional
может использоваться для необязательного указания идентификатора используемого PlatformTransactionManager
. Это может быть либо имя bean, либо значение квалификатора менеджера транзакций bean. Например, используя нотацию классификатора, следующий код Java