我想开发一个应用程序来连接到多个 Oracle 数据库并从每个数据库的同一个表中获取数据。
我尝试对每个数据库使用多个数据源并从表中获取数据。
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/