文章目錄
- 資料源是什麼
- 一、spring中是如何處理各種資料源的?
-
- 1.開搞springboot
- 2.建立一個測試類
- 二、有了如上的理論,那麼想想動态切換資料源吧
-
- 參考若依的動态資料源配置
- 總結
資料源是什麼
資料源,對于java來說,就是可用的資料庫,那麼我平時開發的springboot springcloud項目,那麼也就是yml或者properties中的連結資訊, 例如 mysql redis influx mongodb sqlserver clickhouse nebula-graph …
一般在spring中,都已經對其做好了封裝
一、spring中是如何處理各種資料源的?
那就不得不說下JdbcTemplate 了,隻要是各種遵循了jdbc标準的資料源,也就是大部分的關系型資料庫,都是可以通過它來操作的;簡直就是神奇~~ 怎麼使用呢?
1.開搞springboot
搞一個springboot項目 由于我使用了mysql,是以還引入了mysql驅動包
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
然後在yml加入相應配置
spring:
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://xxxxx:3307/yuque
username: root
password: 123456
2.建立一個測試類
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
class WordApplicationTests1 {
@Test
void contextLoads() {
}
@Autowired
JdbcTemplate jdbcTemplate;
@SneakyThrows
@Test
public void query() {
List<Bom> bomList = jdbcTemplate.query("select DISTINCT * from bom", new BeanPropertyRowMapper<>(Bom.class));
System.out.println(JSONUtil.toJsonStr(bomList));
}
}
相當于可以了,用的就是yml中的配置查詢的資料庫
- 我有一個想法,我想查詢一個其他的庫的資料,但是之前的yml中的我還想用
改造後,變成了
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
class WordApplicationTests1 {
@Test
void contextLoads() {
}
@Autowired
JdbcTemplate jdbcTemplate;
@SneakyThrows
@Test
public void query() {
List<Bom> bomList = jdbcTemplate.query("select DISTINCT * from bom", new BeanPropertyRowMapper<>(Bom.class));
System.out.println(JSONUtil.toJsonStr(bomList));
Properties properties = new Properties();
properties.put("url", "jdbc:mysql://localhost:3306/test?useSSL=false&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&transformedBitIsBoolean=true&tinyInt1isBit=false&allowMultiQueries=true&serverTimezone=GMT%2B8&allowPublicKeyRetrieval=true");
properties.put("username", "root");
properties.put("driverClassName", "com.mysql.jdbc.Driver");
properties.put("password", "root");
DataSource dataSource = DruidDataSourceFactory.createDataSource(properties);
JdbcTemplate template = new JdbcTemplate(dataSource);
List<Bom> list = template.query("select * from bom", new BeanPropertyRowMapper<>(Bom.class));
System.out.println(JSONUtil.toJsonStr(list));
}
}
還是能用的,兩個都能查詢出資料
那…請小夥伴思考下,如果是用jdbc弄一個動态資料源,是不是也不是很難,我需要用哪個庫的資訊,就讓他加載哪個庫的配置資訊就ok了呀.對吧?
甚至,我可以将配置資訊放入資料庫中,啟動後,一次性加載到記憶體,并執行個體化相應的datasource 執行個體,然後在執行個體化相應的jdbctemplete,放入到的全局中,那麼我就可以自如切換了!!!
二、有了如上的理論,那麼想想動态切換資料源吧
參考若依的動态資料源配置
若依
大體思路如下:
- 首先利用本地線程搞一個緩存,目的是為了存放目前可用的資料源,這樣就可以設定/移除 某個資料源了;
DynamicDataSourceContextHolder 僅僅是個緩存
- 由于為了使用友善,是以他自定義了注解,用來切換資料源,也就是更改上面的目前線程緩存,那麼自定義之後,就需要通過切面去實作這個自定義的注解,裡面的中心思想就是擷取傳入的可用資料源(可能有多個),替換之為目前資料源(隻能有一個);
DataSourceAspect 切面實作切換
- 那麼多個資料源是從哪裡來的呢,是在項目啟動的時候,他就已經把可用資料源都執行個體化好了,然後存放起來了,就像我之前分析的那樣,關鍵點就是 實作這個方法 AbstractRoutingDataSource 其中 放入一個map 就是資料源本尊了
DruidConfig 把所有資料源都加載進去了
- 之後就可以通過map.getkey 那樣,擷取到自己想要的資料源了;然後更改本地線程的資料源
- 切換之後,查詢的時候,就會重新查詢到目前設定後的資料源,然後再去查詢
重點中的重點
DynamicDataSource extends AbstractRoutingDataSource
@Override
protected Object determineCurrentLookupKey(){
return DynamicDataSourceContextHolder.getDataSourceType();// 每次執行都會重新擷取新值
}
總結
通過此次JdbcTemplate 的資料源切換,想到了之前看過的若依項目中的多資料源切換問題,這次帶着我自己的想法去看,果然再次閱讀,收獲頗豐;算是徹底看懂了吧;
希望我的了解能為你帶來啟發