Подтвердить что ты не робот

@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 аннотированных конфигураций?

4b9b3361

Ответ 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