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

Как настроить управление транзакциями для работы с двумя разными db в Spring?

У меня есть 2 базы данных (MySql и HSQLDB). Я настроил 2 источника данных и 2 EntityManagerFactory beans. Я также могу настроить 2 соответствующих JpaTransactionManager beans.

Но я не знаю, как указать, какие из них должны использоваться для управления транзакциями для конкретного класса обслуживания. Я хочу использовать аннотацию @Transactional для этой цели, но на самом деле могу указать только один из txManagers:

<tx:annotation-driven transaction-manager="manager"/>

Каков выход из этой ситуации?

4b9b3361

Ответ 1

javadoc для JpaTransactionManager имеет несколько советов по этому поводу:

Этот менеджер транзакций подходит для приложений, которые используют один JPA EntityManagerFactory для доступ к транзакционным данным. JTA (обычно через JtaTransactionManager) необходимо для доступа к нескольким транзакционным ресурсов в рамках одной транзакции. Обратите внимание, что вам необходимо настроить JPA, соответственно, чтобы принять участие в JTA сделки.

Другими словами, если вы обнаружите себя с несколькими менеджерами сущностей с соответствующими менеджерами tx, вам следует рассмотреть возможность использования одного JtaTransactionManager вместо. Менеджеры сущностей должны иметь возможность участвовать в транзакциях JTA, и это даст вам полную транзакцию для обоих менеджеров сущностей, не опасаясь, чтобы беспокоиться о том, какой менеджер сущностей вы находитесь в любой момент.

Конечно, JtaTransactionManager требует полного сервера приложений, поддерживающего JTA, а не движка серфинга ванили, такого как Tomcat.

Ответ 2

Объявите свой <tx:annotation-driven> без атрибута transaction-manager, объявите квалификаторы для менеджеров транзакций следующим образом:

<bean id="jpaTransactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
    <property name="entityManagerFactory" ref="entityManagerFactory" />
    <qualifier value="txManager1"/>
</bean>

Используйте этот определитель в @Transactional в качестве значения для выбора одного из менеджеров транзакций:

@Transactional("txManager1")

или, с большим количеством свойств:

@Transactional(value = "txManager1", readOnly = true)   

Ответ 3

С тех пор как после долгого времени с правильных ответов.

Скаффман может быть правильным с точки зрения удобства использования JpaTransactionManager для нескольких баз данных.

Но есть рабочее решение для использования 2 разных баз данных с двумя разными JpaTransactionManager.

  @Bean(name = "db2TransactionManager")
  public PlatformTransactionManager transactionManager2() throws NamingException {
    JpaTransactionManager txManager = new JpaTransactionManager(entityManagerFactory());
    return txManager;
  }

  @Bean
  @Primary
  public PlatformTransactionManager transactionManager() throws Exception {
     JpaTransactionManager txManager = new JpaTransactionManager(entityManagerFactory());
    txManager.setNestedTransactionAllowed(true);
    return txManager;
  }

@Primary следует использовать для указания тех, где вы не указываете имя квалификатора в @Transactional

Ответ 4

Вы должны указать два менеджера транзакций для этого в application-context.xml, как показано ниже:

<tx:annotation-driven transaction-manager="manager1"/>
<tx:annotation-driven transaction-manager="manager2"/>
Атрибут

@Transactional теперь будет использовать соответствующий менеджер транзакций.