java - Spring Boot中如何连接多个数据库

标签 java database oracle spring-boot jpa

我想开发一个应用程序来连接到多个 Oracle 数据库并从每个数据库的同一个表中获取数据。

我尝试对每个数据库使用多个数据源并从表中获取数据。

资源:https://medium.com/@joeclever/using-multiple-datasources-with-spring-boot-and-spring-data-6430b00c02e7

DB1 配置:

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(entityManagerFactoryRef = "CU1EntityManagerFactory", basePackages = {
      "com.javatechie.multiple.ds.api.cu1.repository" })
public class CU1Config {
   @Primary
   @Bean(name = "CU1DataSource")
   @ConfigurationProperties(prefix = "spring.cu1.datasource")
   public DataSource dataSource() {
      return DataSourceBuilder.create().build();
   }

   @Primary
   @Bean(name = "CU1EntityManagerFactory")
   public LocalContainerEntityManagerFactoryBean CU1EntityManagerFactory(EntityManagerFactoryBuilder builder,
                                                        @Qualifier("CU1DataSource") DataSource dataSource) {
      HashMap<String, Object> properties = new HashMap<>();
      properties.put("hibernate.hbm2ddl.auto", "update");
      properties.put("hibernate.dialect", "org.hibernate.dialect.Oracle12cDialect");
      return builder.dataSource(dataSource).properties(properties)
            .packages("com.javatechie.multiple.ds.api.model").persistenceUnit("Unit").build();
   }

}

DB2 配置:

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(entityManagerFactoryRef = "CU2EntityManagerFactory", basePackages = {
      "com.javatechie.multiple.ds.api.cu2.repository" })
public class CU2Config {

   @Bean(name = "CU2DataSource")
   @ConfigurationProperties(prefix = "spring.cu2.datasource")
   public DataSource dataSource() {
      return DataSourceBuilder.create().build();
   }

   @Bean(name = "CU2EntityManagerFactory")
   public LocalContainerEntityManagerFactoryBean CU2EntityManagerFactory(EntityManagerFactoryBuilder builder,
                                                        @Qualifier("CU2DataSource") DataSource dataSource) {
      HashMap<String, Object> properties = new HashMap<>();
      properties.put("hibernate.hbm2ddl.auto", "update");
      properties.put("hibernate.dialect", "org.hibernate.dialect.Oracle12cDialect");
      return builder.dataSource(dataSource).properties(properties)
            .packages("com.javatechie.multiple.ds.api.model").persistenceUnit("Unit").build();
   }

}

但是我面临的问题是,对于每个数据源,我都必须创建一个单独的配置类以及一个专用的存储库和服务,这是代码可重复性,尽管每个数据库的工作都是相同的,从特定的表中获取数据。

而且将来如果我想添加任何新数据库,我必须再次重复上述相同的过程。

任何有关更好的代码可重用性方法的帮助都将受到高度赞赏。

最佳答案

如果你要创建一个严肃的服务,你应该只知道如何配置它们,如何使用它们,以及如何通过 Spring 控制所有数据库的事务。

您可以在 https://github.com/surasint/surasint-examples/tree/master/spring-boot-jdbi/10_spring-boot-two-databases 中看到可运行的示例和一些说明(查看 README.txt 中可以尝试的内容)

我在这里复制了一些代码。

首先你必须像这样设置application.properties

#Database
database1.datasource.url=jdbc:mysql://localhost/testdb
database1.datasource.username=root
database1.datasource.password=root
database1.datasource.driver-class-name=com.mysql.jdbc.Driver

database2.datasource.url=jdbc:mysql://localhost/testdb2
database2.datasource.username=root
database2.datasource.password=root
database2.datasource.driver-class-name=com.mysql.jdbc.Driver

然后将它们定义为提供者(@Bean),如下所示:

@Bean(name = "datasource1")
@ConfigurationProperties("database1.datasource")
@Primary
public DataSource dataSource(){
    return DataSourceBuilder.create().build();
}

@Bean(name = "datasource2")
@ConfigurationProperties("database2.datasource")
public DataSource dataSource2(){
    return DataSourceBuilder.create().build();
}

注意我有@Bean(name="datasource1")@Bean(name="datasource2"),那么当我们需要数据源时就可以使用它例如 @Qualifier("datasource1")@Qualifier("datasource2")

@Qualifier("datasource1")
@Autowired
private DataSource dataSource;

如果您确实关心事务,则必须为它们定义 DataSourceTransactionManager,如下所示:

@Bean(name="tm1")
@Autowired
@Primary
DataSourceTransactionManager tm1(@Qualifier ("datasource1") DataSource datasource) {
    DataSourceTransactionManager txm  = new DataSourceTransactionManager(datasource);
    return txm;
}

@Bean(name="tm2")
@Autowired
DataSourceTransactionManager tm2(@Qualifier ("datasource2") DataSource datasource) {
    DataSourceTransactionManager txm  = new DataSourceTransactionManager(datasource);
    return txm;
}

然后你就可以像这样使用它

@Transactional //this will use the first datasource because it is @primary

@Transactional("tm2")

最重要的部分,你很难在任何地方找到示例:如果你想要一个提交/回滚两个数据库事务的方法,你需要 tm1 和 tm2 的 ChainedTransactionManager ,如下所示:

@Bean(name = "chainedTransactionManager")
public ChainedTransactionManager getChainedTransactionManager(@Qualifier ("tm1") DataSourceTransactionManager tm1, @Qualifier ("tm2") DataSourceTransactionManager tm2){
    return new ChainedTransactionManager(tm1, tm2);
}

要使用它,请在方法 @Transactional(value="chainedTransactionManager") 中添加此注释

@Transactional(value="chainedTransactionManager")
public void insertAll() {
    UserBean test = new UserBean();
    test.setUsername("username" + new Date().getTime());
    userDao.insert(test);

    userDao2.insert(test);
}

这应该足够了。请参阅上面链接中的示例和详细信息。

关于java - Spring Boot中如何连接多个数据库,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71607764/

相关文章:

sql - ORACLE SQL :Get all integers between two numbers

java - 得墨忒耳法则 - 为什么我需要使用 setter/getter ?

java - EhCache 的 CacheStatistics getCacheHits 与 getInMemoryHits

java - 如何从 ftp 服务器获取文件的路径?

php - 将不同SQL Access 记录的值取为1

java - Hibernate 查询语言中四舍五入到小数点后两位

java - 您如何知道如何限制可以进入基本群聊应用程序服务器的客户端数量? (最多 10 个)

sql - 在列中放置默认值有什么好处?

php - 同时插入多个值,如单变量和数组变量

sql - SQL 过程可以返回表吗?