使用SpringBoot 配置Oracle和H2雙數(shù)據(jù)源及問題
在上節(jié)使用了H2之后感覺很爽,很輕便,正好有個項目要求簡單,最好不適用外部數(shù)據(jù)庫,于是就想著把H2數(shù)據(jù)庫集成進(jìn)來,這個系統(tǒng)已經(jīng)存在了一個Oracle,正好練習(xí)下配置多數(shù)據(jù)源,而在配置多數(shù)據(jù)源時,H2的schema配置不生效真是花了我好長時間才解決。。。所以也記錄一下
配置POM
<!-- oracle --> <dependency> <groupId>com.github.noraui</groupId> <artifactId>noraui</artifactId> <version>2.4.0</version> </dependency> <!-- h2--> <dependency> <groupId>com.h2database</groupId> <artifactId>h2</artifactId> <version>1.4.197</version> </dependency> <!-- mybatisplus --> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.1.1</version> </dependency>
配置yml
spring: http: encoding: charset: UTF-8 enabled: true force: true datasource: driver-class-name: org.h2.Driver schema: classpath:h2/schema-h2.sql data: classpath:h2/data-h2.sql jdbc-url: jdbc:h2:file:D:/Cache/IdeaWorkSpace/BigData/CustomerModel/src/main/resources/h2/data/h2_data username: root password: a123456 initialization-mode: always oracle: driver-class-name: oracle.jdbc.driver.OracleDriver jdbc-url: jdbc:oracle:thin:@xxx:1521:cmis username: xxx password: xxx h2: console: enabled: true path: /h2-console
可以看到配置中配置了兩個數(shù)據(jù)源,主數(shù)據(jù)源是H2,第二個數(shù)據(jù)源是Oracle,接下來是通過配置類來注入數(shù)據(jù)源
配置注入
配置H2主數(shù)據(jù)源
package com.caxs.warn.config; import org.apache.ibatis.session.SqlSessionFactory; import org.mybatis.spring.SqlSessionFactoryBean; import org.mybatis.spring.annotation.MapperScan; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.jdbc.DataSourceBuilder; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.datasource.DataSourceTransactionManager; import javax.sql.DataSource; /** * @Author: TheBigBlue * @Description: * @Date: 2019/9/18 */ @Configuration @MapperScan(basePackages = "com.caxs.warn.mapper.h2", sqlSessionFactoryRef = "h2SqlSessionFactory") public class H2DSConfig { @Bean(name = "h2DataSource") @ConfigurationProperties(prefix = "spring.datasource") public DataSource dataSource() { return DataSourceBuilder.create().build(); } @Bean(name = "h2TransactionManager") public DataSourceTransactionManager transactionManager() { return new DataSourceTransactionManager(this.dataSource()); } @Bean(name = "h2SqlSessionFactory") public SqlSessionFactory sqlSessionFactory(@Qualifier("h2DataSource") DataSource dataSource) throws Exception { final SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean(); sessionFactory.setDataSource(dataSource); sessionFactory.getObject().getConfiguration().setMapUnderscoreToCamelCase(true); return sessionFactory.getObject(); } @Bean(name = "h2Template") public JdbcTemplate h2Template(@Qualifier("h2DataSource") DataSource dataSource) { return new JdbcTemplate(dataSource); } }
配置oracle從數(shù)據(jù)源
package com.caxs.warn.config; import org.apache.ibatis.session.SqlSessionFactory; import org.mybatis.spring.SqlSessionFactoryBean; import org.mybatis.spring.annotation.MapperScan; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.jdbc.DataSourceBuilder; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.datasource.DataSourceTransactionManager; import javax.sql.DataSource; /** * @Author: TheBigBlue * @Description: * @Date: 2019/9/18 */ @Configuration @MapperScan(basePackages = "com.caxs.warn.mapper.oracle",sqlSessionFactoryRef = "oracleSqlSessionFactory") public class OracleDSConfig { @Bean(name = "oracleDataSource") @ConfigurationProperties(prefix = "spring.datasource.oracle") public DataSource dataSource() { return DataSourceBuilder.create().build(); } @Bean(name = "oracleTransactionManager") public DataSourceTransactionManager transactionManager() { return new DataSourceTransactionManager(this.dataSource()); } @Bean(name = "oracleSqlSessionFactory") public SqlSessionFactory sqlSessionFactory(@Qualifier("oracleDataSource") DataSource dataSource) throws Exception { final SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean(); sessionFactory.setDataSource(dataSource); sessionFactory.getObject().getConfiguration().setMapUnderscoreToCamelCase(true); return sessionFactory.getObject(); } @Bean(name = "oracleTemplate") public JdbcTemplate oracleTemplate(@Qualifier("oracleDataSource") DataSource dataSource) { return new JdbcTemplate(dataSource); } }
問題
Schema “classpath:h2/schema-h2.sql” not found
經(jīng)過上面的配置就可以使用雙數(shù)據(jù)源了,但是當(dāng)我們測試時會發(fā)現(xiàn)報如下錯誤:Schema “classpath:h2/schema-h2.sql” not found,這個問題我也是找了好久,因為在配置但數(shù)據(jù)源的時候沒有這個問題的,在配置多數(shù)據(jù)源才有了這個問題。
單數(shù)據(jù)源時,是直接SpringBoot自動配置DataSource的,這個時候是正常的,而當(dāng)配置多數(shù)據(jù)源時,我們是通過@Configuration來配置數(shù)據(jù)源的,懷疑問題出在 DataSourceBuilder 創(chuàng)建數(shù)據(jù)源這個類上,而單數(shù)據(jù)源自動裝載時不會出現(xiàn)這樣的問題。然后百度搜了下這個DataSourceBuilder,看到文章中實例的配置中schema是這樣寫的:
package com.caxs.warn.service; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.ApplicationArguments; import org.springframework.boot.ApplicationRunner; import org.springframework.core.io.ClassPathResource; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.stereotype.Component; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; /** * @Author: TheBigBlue * @Description: 服務(wù)啟動后,初始化數(shù)據(jù)庫 * @Date: 2019/9/19 */ @Component public class ApplicationRunnerService implements ApplicationRunner { private static final Logger LOGGER = LoggerFactory.getLogger(ApplicationRunnerService.class); @Autowired @Qualifier("h2Template") private JdbcTemplate h2Template; @Value("${invoke.schema.location}") private String schema; @Value("${invoke.data.location}") private String data; /** * @Author: TheBigBlue * @Description: 項目啟動,執(zhí)行sql文件初始化 * @Date: 2019/9/19 * @Param args: * @Return: **/ @Override public void run(ApplicationArguments args) { String schemaContent = this.getFileContent(schema); String dataContent = this.getFileContent(data); h2Template.execute(schemaContent); h2Template.execute(dataContent); } /** * @Author: TheBigBlue * @Description: 獲取classpath下sql文件內(nèi)容 * @Date: 2019/9/19 * @Param filePath: * @Return: **/ private String getFileContent(String filePath) { BufferedReader bufferedReader = null; String string; StringBuilder data = new StringBuilder(); try { ClassPathResource classPathResource = new ClassPathResource(filePath); bufferedReader = new BufferedReader(new InputStreamReader(classPathResource.getInputStream())); while ((string = bufferedReader.readLine()) != null) { data.append(string); } } catch (IOException e) { LOGGER.error("加載ClassPath資源失敗", e); }finally { if(null != bufferedReader){ try { bufferedReader.close(); } catch (IOException e) { e.printStackTrace(); } } } return data.toString(); } }
抱著嘗試的態(tài)度改了下,發(fā)現(xiàn)果然沒問題了!!原來是在SpringBoot2.0之后schema對應(yīng)的DataSourceProperties類中schema屬性是一個List,所以需要前面加 - (yml中加-映射集合),記錄下防止后面再踩坑。
Table “USER” not found; SQL statement:
這個問題也是在只有配置多數(shù)據(jù)源時才會碰到的問題,就是配置的spring.datasource.schema和spring.datasource.data無效。這個我看了下如果是配置單數(shù)據(jù)源,springboot自動加載Datasource,是沒問題的,但是現(xiàn)在是我們自己維護(hù)的datasource: return DataSourceBuilder.create().build();所以感覺還是DataSourceBuilder在加載數(shù)據(jù)源的時候的問題,但是還是沒有找到原因。有網(wǎng)友說必須加initialization-mode: ALWAYS這個配置,但是我配置后也是不能用的。
最后沒辦法就配置了一個類,在springboot啟動后,自己加載文件,讀取其中的sql內(nèi)容,然后用jdbcTemplate去執(zhí)行了下,模擬了下初始化的操作。。。后面如果有時間再來解決這個問題。
package com.caxs.warn.service; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.ApplicationArguments; import org.springframework.boot.ApplicationRunner; import org.springframework.core.io.ClassPathResource; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.stereotype.Component; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; /** * @Author: TheBigBlue * @Description: 服務(wù)啟動后,初始化數(shù)據(jù)庫 * @Date: 2019/9/19 */ @Component public class ApplicationRunnerService implements ApplicationRunner { private static final Logger LOGGER = LoggerFactory.getLogger(ApplicationRunnerService.class); @Autowired @Qualifier("h2Template") private JdbcTemplate h2Template; @Value("${invoke.schema.location}") private String schema; @Value("${invoke.data.location}") private String data; /** * @Author: TheBigBlue * @Description: 項目啟動,執(zhí)行sql文件初始化 * @Date: 2019/9/19 * @Param args: * @Return: **/ @Override public void run(ApplicationArguments args) { String schemaContent = this.getFileContent(schema); String dataContent = this.getFileContent(data); h2Template.execute(schemaContent); h2Template.execute(dataContent); } /** * @Author: TheBigBlue * @Description: 獲取classpath下sql文件內(nèi)容 * @Date: 2019/9/19 * @Param filePath: * @Return: **/ private String getFileContent(String filePath) { BufferedReader bufferedReader = null; String string; StringBuilder data = new StringBuilder(); try { ClassPathResource classPathResource = new ClassPathResource(filePath); bufferedReader = new BufferedReader(new InputStreamReader(classPathResource.getInputStream())); while ((string = bufferedReader.readLine()) != null) { data.append(string); } } catch (IOException e) { LOGGER.error("加載ClassPath資源失敗", e); }finally { if(null != bufferedReader){ try { bufferedReader.close(); } catch (IOException e) { e.printStackTrace(); } } } return data.toString(); } }
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
springcloud檢索中間件?ElasticSearch?分布式場景的使用
單機(jī)的elasticsearch做數(shù)據(jù)存儲,必然面臨兩個問題:海量數(shù)據(jù)存儲問題、單點故障問題,本文重點給大家介紹springcloud檢索中間件?ElasticSearch?分布式場景的運用,感興趣的朋友跟隨小編一起看看吧2023-10-10Spring-基于Spring使用自定義注解及Aspect實現(xiàn)數(shù)據(jù)庫切換操作
這篇文章主要介紹了Spring-基于Spring使用自定義注解及Aspect實現(xiàn)數(shù)據(jù)庫切換操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-09-09Java設(shè)計模式之觀察者模式(Observer模式)
這篇文章主要介紹了Java設(shè)計模式之觀察者模式(Observer模式),文中有非常詳細(xì)的代碼示例,對正在學(xué)習(xí)java的小伙伴們有非常好的幫助,需要的朋友可以參考下2021-04-04java HashMap和HashTable的區(qū)別詳解
這篇文章主要介紹了java HashMap和HashTable的區(qū)別詳解的相關(guān)資料,需要的朋友可以參考下2016-12-12