Spring Boot中的多个事务管理器,用于不同的EntityManagers

时间:2015-03-26 06:50:38

标签: spring spring-boot

我需要从单个应用程序连接到两个不同的数据库。问题是我的appEntityManager没有与之关联的事务管理器,我不知道该怎么做。 @Primary adminEntityManager能够使用spring boot提供的那个,没有任何问题,如here所述。

  

上面的配置几乎可以单独使用。完成了   你需要为这两个配置TransactionManagers的图片   EntityManagers也是如此。其中一个可以默认选中   如果你将它标记为@Primary,则在Spring Boot中使用JpaTransactionManager。该   其他必须明确地注入新实例。或者您   也许可以使用跨越两者的JTA事务管理器。

我已使用

注释了配置
@EnableTransactionManagement

这是相关豆

@Bean
@ConfigurationProperties(prefix = "datasource.app")
public DataSource appDataSource() {
    return DataSourceBuilder.create().build();
}

@Bean
@Primary
@ConfigurationProperties(prefix = "datasource.admin")
public DataSource adminDataSource() {
    return DataSourceBuilder.create().build();
}

@Bean
public LocalContainerEntityManagerFactoryBean appEntityManagerFactory(
        final EntityManagerFactoryBuilder builder) {
    return builder
            .dataSource(appDataSource())
            .packages("au.com.mycompany.app.bomcommon.domain")
            .persistenceUnit("appPersistentUnit")
            .build();
}

@Bean
@Primary
public LocalContainerEntityManagerFactoryBean adminEntityManagerFactory(
        final EntityManagerFactoryBuilder builder) {
    return builder
            .dataSource(adminDataSource())
            .packages("au.com.mycompany.app.bombatch")
            .persistenceUnit("adminPersistentUnit")
            .build();
}

//I thought this would do it but I am getting an exception
//No qualifying bean of type [org.springframework.transaction.PlatformTransactionManager] is defined: expected single matching bean but found 2: appTransactionManager,transactionManager
@Bean
public JpaTransactionManager appTransactionManager(@Qualifier("appEntityManagerFactory") final EntityManagerFactory emf) {
    JpaTransactionManager transactionManager = new JpaTransactionManager();
    transactionManager.setEntityManagerFactory(emf);
    return transactionManager;
}

更新

我最后以不同的方式做到了。 see here

2 个答案:

答案 0 :(得分:4)

看看是否有效:

@Bean
@Primary
@ConfigurationProperties(prefix = "datasource.admin")
public DataSource adminDS() { ... }

@Bean
@Primary
public LocalContainerEntityManagerFactoryBean adminEMF(...) { ... }

@Bean
@Primary
public JpaTransactionManager adminTM(...) { ... }

@Bean
public LocalContainerEntityManagerFactoryBean appEMF(...) { ... }

@Bean
public JpaTransactionManager appTM(...) { ... }

我对您的配置进行的唯一更改是明确声明管理员端的事务管理器,并将该事务管理器标记为默认值。

答案 1 :(得分:0)

请参阅以下更改。这个对我有用。创建了3个数据源,3个会话工厂和3个事务管理器。如下将这些事务管理器添加到chainedTransaction中:

                    @Configuration
                    @EnableTransactionManagement
                    public class HibernateConfiguration implements TransactionManagementConfigurer {


                        @Bean("chainedTransactionManager")
                        public PlatformTransactionManager transactionManager(
                                @Qualifier("transactionManager1") final HibernateTransactionManager transactionManager1,
                                @Qualifier("transactionManager2") final HibernateTransactionManager transactionManager2,
                                @Qualifier("transactionManager3") final HibernateTransactionManager transactionManager3) {

                            return new ChainedTransactionManager(transactionManager1, transactionManager2, transactionManager3);
                        }

                        @Override
                        public PlatformTransactionManager annotationDrivenTransactionManager() {
                            // TODO Auto-generated method stub
                            return transactionManager(oneTransactionManager(), twoTransactionManager(), threeTransactionManager());
                        }


                @Bean(name = "oneDataSource", destroyMethod="")
                      public DataSource oneDataSource() throws IllegalArgumentException, NamingException, SQLException {
                            HikariConfig hkConfig = new HikariConfig();
                            System.out.println(env.getRequiredProperty("spring1-datasource.jdbcUrl"));
                            hkConfig.setJdbcUrl(env.getRequiredProperty("spring1-datasource.jdbcUrl"));
                            hkConfig.setUsername(env.getRequiredProperty("spring1-datasource.username"));
                            hkConfig.setPassword(env.getRequiredProperty("spring1-datasource.password"));
                            hkConfig.setDriverClassName(env.getRequiredProperty("spring1-datasource.driverClassName"));
                            return new HikariDataSource(hkConfig);
                        }

                @Bean(name="oneSessionFactory")
                @Qualifier("oneSessionFactory") 
               public LocalSessionFactoryBean oneSessionFactory() throws IllegalArgumentException, NamingException, SQLException {
                LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
                sessionFactory.setDataSource(oneDataSource());
                  sessionFactory.setPackagesToScan(env.getRequiredProperty("entitymanager.packagesToScan"));
                  Properties hibernateProperties = new Properties();
                  hibernateProperties.put("hibernate.dialect", env.getRequiredProperty("hibernate.dialect"));
                  hibernateProperties.put("hibernate.show_sql", env.getRequiredProperty("hibernate.show_sql"));
                  sessionFactory.setHibernateProperties(hibernateProperties);
                return sessionFactory;

              }



        @Bean(name="transactionManager1")
          public HibernateTransactionManager oneTransactionManager() {
              HibernateTransactionManager oneTransactionManager = new HibernateTransactionManager();
              try {
                oneTransactionManager.setSessionFactory(oneSessionFactory().getObject());
                } catch (IllegalArgumentException | NamingException | SQLException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
              return oneTransactionManager 
          }





    @Bean(name = "twoDataSource", destroyMethod="")
          public DataSource twoDataSource() throws IllegalArgumentException, NamingException, SQLException {
                HikariConfig hkConfig = new HikariConfig();
                System.out.println(env.getRequiredProperty("spring2-datasource.jdbcUrl"));
                hkConfig.setJdbcUrl(env.getRequiredProperty("spring2-datasource.jdbcUrl"));
                hkConfig.setUsername(env.getRequiredProperty("spring2-datasource.username"));
                hkConfig.setPassword(env.getRequiredProperty("spring2-datasource.password"));
                hkConfig.setDriverClassName(env.getRequiredProperty("spring2-datasource.driverClassName"));
                return new HikariDataSource(hkConfig);
            }



@Bean(name="twoSessionFactory")
    @Qualifier("twoSessionFactory") 
   public LocalSessionFactoryBean twoSessionFactory() throws IllegalArgumentException, NamingException, SQLException {
    LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
    sessionFactory.setDataSource(twoDataSource());
      sessionFactory.setPackagesToScan(env.getRequiredProperty("entitymanager.packagesToScan"));
      Properties hibernateProperties = new Properties();
      hibernateProperties.put("hibernate.dialect", env.getRequiredProperty("hibernate.dialect"));
      hibernateProperties.put("hibernate.show_sql", env.getRequiredProperty("hibernate.show_sql"));
      sessionFactory.setHibernateProperties(hibernateProperties);
    return sessionFactory;

  }





  @Bean(name="transactionManager2")
  public HibernateTransactionManager twoTransactionManager() {
      HibernateTransactionManager twoTransactionManager = new HibernateTransactionManager();
      try {
        twoTransactionManager.setSessionFactory(twoSessionFactory().getObject());
        } catch (IllegalArgumentException | NamingException | SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
      return twoTransactionManager
  }


@Bean(name = "threeDataSource", destroyMethod="")
      public DataSource threeDataSource() throws IllegalArgumentException, NamingException, SQLException {
            HikariConfig hkConfig = new HikariConfig();
            System.out.println(env.getRequiredProperty("spring3-datasource.jdbcUrl"));
            hkConfig.setJdbcUrl(env.getRequiredProperty("spring3-datasource.jdbcUrl"));
            hkConfig.setUsername(env.getRequiredProperty("spring3-datasource.username"));
            hkConfig.setPassword(env.getRequiredProperty("spring3-datasource.password"));
            hkConfig.setDriverClassName(env.getRequiredProperty("spring3-datasource.driverClassName"));
            return new HikariDataSource(hkConfig);
        }


    @Bean(name="threeSessionFactory")
    @Qualifier("threeSessionFactory") 
   public LocalSessionFactoryBean threeSessionFactory() throws IllegalArgumentException, NamingException, SQLException {
    LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
    sessionFactory.setDataSource(threeDataSource());
      sessionFactory.setPackagesToScan(env.getRequiredProperty("entitymanager.packagesToScan"));
      Properties hibernateProperties = new Properties();
      hibernateProperties.put("hibernate.dialect", env.getRequiredProperty("hibernate.dialect"));
      hibernateProperties.put("hibernate.show_sql", env.getRequiredProperty("hibernate.show_sql"));
      sessionFactory.setHibernateProperties(hibernateProperties);
    return sessionFactory;

  }





  @Bean(name="transactionManager3")
  public HibernateTransactionManager threeTransactionManager() {
      HibernateTransactionManager threeTransactionManager = new HibernateTransactionManager();
      try {
        threeTransactionManager.setSessionFactory(threeSessionFactory().getObject());
        } catch (IllegalArgumentException | NamingException | SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
      return threeTransactionManager
  }

                           }