<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          SpringBoot 的多數(shù)據(jù)源配置

          共 9646字,需瀏覽 20分鐘

           ·

          2021-12-14 12:44

          2020-12-29 杭州 雪

          最近在項目開發(fā)中,需要為一個使用 MySQL 數(shù)據(jù)庫的 SpringBoot 項目,新添加一個 PLSQL 數(shù)據(jù)庫數(shù)據(jù)源,那么就需要進(jìn)行 SpringBoot 的多數(shù)據(jù)源開發(fā)。代碼很簡單,下面是實(shí)現(xiàn)的過程。

          環(huán)境準(zhǔn)備

          實(shí)驗(yàn)環(huán)境:

          • JDK 1.8
          • SpringBoot 2.4.1
          • Maven 3.6.3
          • MySQL 5.7

          因?yàn)槲冶镜刂挥?MySQL 數(shù)據(jù)庫,為了方便演示,我會在啟動一個本地 MySQL,在 MySQL 創(chuàng)建兩個數(shù)據(jù)庫,每個庫中均有一個表,以此進(jìn)行演示。

          數(shù)據(jù)準(zhǔn)備

          本地 MySQL 端口默認(rèn)不做改動,端口號 3306。

          創(chuàng)建數(shù)據(jù)庫 demo1,demo2。在 demo1 數(shù)據(jù)庫中創(chuàng)建表 book。

          --?create?table
          create?table?Book
          (
          ????id??????????int?auto_increment
          ????????primary?key,
          ????author??????varchar(64)??not?null?comment?'作者信息',
          ????name????????varchar(64)??not?null?comment?'書籍名稱',
          ????price???????decimal??????not?null?comment?'價格',
          ????createTime??datetime?????null?comment?'上架時間',
          ????description?varchar(128)?null?comment?'書籍描述'
          );
          --?insert?data
          INSERT?INTO?demo1.Book?(id,?author,?name,?price,?createTime,?description)?VALUES?(1,?'金庸',?'笑傲江湖',?13,?'2020-12-19?15:26:51',?'武俠小說');
          INSERT?INTO?demo1.Book?(id,?author,?name,?price,?createTime,?description)?VALUES?(2,?'羅貫中',?'三國演義',?14,?'2020-12-19?15:28:36',?'歷史小說');

          在 demo2 數(shù)據(jù)庫中創(chuàng)建表 user。

          --?create?table
          create?table?User
          (
          ????id???????int?auto_increment
          ????????primary?key,
          ????name?????varchar(32)?null?comment?'用戶名稱',
          ????birthday?date????????null?comment?'出生日期'
          )
          ????comment?'用戶信息表';
          --?insert?data
          INSERT?INTO?demo2.User?(id,?name,?birthday)?VALUES?(1,?'金庸',?'1924-03-10');
          INSERT?INTO?demo2.User?(id,?name,?birthday)?VALUES?(2,?'羅貫中',?'1330-01-10');

          數(shù)據(jù)準(zhǔn)備完畢,表中都新增了兩條數(shù)據(jù)。

          項目準(zhǔn)備

          這里直接從 Spring 官方上初始化一個添加了 web、lombok、mybatis、mysql 依賴的 SpringBoot 項目。

          訪問直接下載:

          https://start.spring.io/starter.zip?type=maven-project&language=java&bootVersion=2.4.1.RELEASE&baseDir=demo&groupId=com&artifactId=wdbyte&name=demo&description=Demo%20project%20for%20Spring%20Boot&packageName=com.wdbyte.demo&packaging=jar&javaVersion=1.8&dependencies=mybatis,lombok,web,mysql

          如果你手上已經(jīng)有了一個 SpringBoot 項目,既然你想改造成多數(shù)據(jù)源,那么你應(yīng)該已經(jīng)有了一個數(shù)據(jù)源了,如果新增的數(shù)據(jù)源數(shù)據(jù)庫和目前的一致,你可以直接使用你的項目進(jìn)行改造測試。

          多數(shù)據(jù)源

          SpringBoot 的多數(shù)據(jù)源開發(fā)十分簡單,如果多個數(shù)據(jù)源的數(shù)據(jù)庫相同,比如都是 MySQL,那么依賴是不需要任何改動的,只需要進(jìn)行多數(shù)據(jù)源配置即可。

          如果你新增的數(shù)據(jù)庫數(shù)據(jù)源和目前的數(shù)據(jù)庫不同,記得引入新數(shù)據(jù)庫的驅(qū)動依賴,比如 MySQL 和 PGSQL。

          <dependency>
          ?<groupId>mysqlgroupId>
          ?<artifactId>mysql-connector-javaartifactId>
          ?<scope>runtimescope>
          dependency>

          <dependency>
          ????<groupId>org.postgresqlgroupId>
          ????<artifactId>postgresqlartifactId>
          ????<version>42.2.7version>
          dependency>

          連接配置

          既然有多個數(shù)據(jù)源,因?yàn)閿?shù)據(jù)庫用戶名密碼可能不相同,所以是需要配置多個數(shù)據(jù)源信息的,直接在 properties/yml 中配置即可。這里要注意根據(jù)配置的屬性名進(jìn)行區(qū)分,同時因?yàn)閿?shù)據(jù)源要有一個默認(rèn)使用的數(shù)據(jù)源,最好在名稱上有所區(qū)分(這里使用 primary 作為主數(shù)據(jù)源標(biāo)識)。

          ########################## 主數(shù)據(jù)源 ##################################
          spring.datasource.primary.jdbc-url=jdbc:mysql://127.0.0.1:3306/demo1?characterEncoding=utf-8&serverTimezone=GMT%2B8
          spring.datasource.primary.driver-class-name=com.mysql.jdbc.Driver
          spring.datasource.primary.username=root
          spring.datasource.primary.password=

          ########################## 第二個數(shù)據(jù)源 ###############################
          spring.datasource.datasource2.jdbc-url=jdbc:mysql://127.0.0.1:3306/demo2?characterEncoding=utf-8&serverTimezone=GMT%2B8
          spring.datasource.datasource2.driver-class-name=com.mysql.jdbc.Driver
          spring.datasource.datasource2.username=root
          spring.datasource.datasource2.password=

          # mybatis
          mybatis.mapper-locations=classpath:mapper/*.xml
          mybatis.type-aliases-package=com.wdbyte.domain

          注意,配置中的數(shù)據(jù)源連接 url 末尾使用的是 jdbc-url.

          因?yàn)槭褂昧?Mybatis 框架,所以 Mybatis 框架的配置信息也是少不了的,指定掃描目錄 mapper 下的mapper xml 配置文件。

          Mybatis 配置

          如何編寫 Mybatis Mapper 或者如何使用工具生成 Mybatis Mapper 不是本文的重點(diǎn),如果你不知道可以參考 Mybatis 官方文檔或者我之前的文章。

          鏈接一:使用 Mybatis(自動生成插件) 訪問數(shù)據(jù)庫

          鏈接二:使用 Mybatis 集成 pagehelper 分頁插件和 mapper 插件

          下面我已經(jīng)按照上面的兩個庫中的兩個表,Book 和 User 表分別編寫相應(yīng)的 Mybatis 配置。

          創(chuàng)建 BookMapper.xmlUserMapper.xml 放到配置文件配置的路徑 mapper 目錄下。創(chuàng)建 UserMapper 和 BookMapper 接口操作類放在不同的目錄。這里注意 Mapper 接口要按數(shù)據(jù)源分開放在不同的目錄中。后續(xù)好使用不同的數(shù)據(jù)源配置掃描不同的目錄,這樣就可以實(shí)現(xiàn)不同的 Mapper 使用不同的數(shù)據(jù)源配置。

          Mybatis 文件配置

          Service 層沒有變化,這里 BookMapper 和 UserMapper 都有一個 selectAll() 方法用于查詢測試。

          多數(shù)據(jù)源配置

          上面你應(yīng)該看到了,到目前為止和 Mybatis 單數(shù)據(jù)源寫法唯一的區(qū)別就是 Mapper 接口使用不同的目錄分開了,那么這個不同點(diǎn)一定會在數(shù)據(jù)源配置中體現(xiàn)。

          主數(shù)據(jù)源

          開始配置兩個數(shù)據(jù)源信息,先配置主數(shù)據(jù)源,配置掃描的 MapperScan 目錄為 com.wdbyte.mapper.primary

          /**
          ?*?主數(shù)據(jù)源配置
          ?*
          ?*?@author?niujinpeng
          ?*?@website:?https://www.wdbyte.com
          ?*?@date?2020/12/19
          ?*/

          @Configuration
          @MapperScan(basePackages?=?{"com.wdbyte.mapper.primary"},?sqlSessionFactoryRef?=?"sqlSessionFactory")
          public?class?PrimaryDataSourceConfig?{

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

          ????@Bean(name?=?"sqlSessionFactory")
          ????@Primary
          ????public?SqlSessionFactory?sqlSessionFactory(@Qualifier("dataSource")?DataSource?dataSource)?throws?Exception?{
          ????????SqlSessionFactoryBean?bean?=?new?SqlSessionFactoryBean();
          ????????bean.setDataSource(dataSource);
          ????????bean.setMapperLocations(new?PathMatchingResourcePatternResolver().getResources("classpath:mapper/*.xml"));
          ????????return?bean.getObject();
          ????}

          ????@Bean(name?=?"transactionManager")
          ????@Primary
          ????public?DataSourceTransactionManager?transactionManager(@Qualifier("dataSource")?DataSource?dataSource)?{
          ????????return?new?DataSourceTransactionManager(dataSource);
          ????}

          ????@Bean(name?=?"sqlSessionTemplate")
          ????@Primary
          ????public?SqlSessionTemplate?sqlSessionTemplate(@Qualifier("sqlSessionFactory")?SqlSessionFactory?sqlSessionFactory)?{
          ????????return?new?SqlSessionTemplate(sqlSessionFactory);
          ????}
          }

          和單數(shù)據(jù)源不同的是這里把

          • dataSource
          • sqlSessionFactory
          • transactionManager
          • sqlSessionTemplate

          都單獨(dú)進(jìn)行了配置,簡單的 bean 創(chuàng)建,下面是用到的一些注解說明。

          • @ConfigurationProperties(prefix = "spring.datasource.primary"):使用spring.datasource.primary 開頭的配置。
          • @Primary :聲明這是一個主數(shù)據(jù)源(默認(rèn)數(shù)據(jù)源),多數(shù)據(jù)源配置時必不可少
          • @Qualifier:顯式選擇傳入的 Bean。

          第二個數(shù)據(jù)源

          第二個數(shù)據(jù)源和主數(shù)據(jù)源唯一不同的只是 MapperScan 掃描路徑和創(chuàng)建的 Bean 名稱,同時沒有 @Primary 主數(shù)據(jù)源的注解。

          /**
          ?*?第二個數(shù)據(jù)源配置
          ?*?
          ?*?@author?niujinpeng
          ?*?@website:?https://www.wdbyte.com
          ?*?@date?2020/12/19
          ?*/

          @Configuration
          @MapperScan(basePackages?=?{"com.wdbyte.mapper.datasource2"},?sqlSessionFactoryRef?=?"sqlSessionFactory2")
          public?class?SecondDataSourceConfig?{

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

          ????@Bean(name?=?"sqlSessionFactory2")
          ????public?SqlSessionFactory?sqlSessionFactory(@Qualifier("dataSource2")?DataSource?dataSource)?throws?Exception?{
          ????????SqlSessionFactoryBean?bean?=?new?SqlSessionFactoryBean();
          ????????bean.setDataSource(dataSource);
          ????????bean.setMapperLocations(new?PathMatchingResourcePatternResolver().getResources("classpath:mapper/*.xml"));
          ????????return?bean.getObject();
          ????}

          ????@Bean(name?=?"transactionManager2")
          ????public?DataSourceTransactionManager?transactionManager(@Qualifier("dataSource2")?DataSource?dataSource)?{
          ????????return?new?DataSourceTransactionManager(dataSource);
          ????}

          ????@Bean(name?=?"sqlSessionTemplate2")
          ????public?SqlSessionTemplate?sqlSessionTemplate(@Qualifier("sqlSessionFactory2")?SqlSessionFactory?sqlSessionFactory)?{
          ????????return?new?SqlSessionTemplate(sqlSessionFactory);
          ????}
          }

          注意:因?yàn)橐呀?jīng)在兩個數(shù)據(jù)源中分別配置了掃描的 Mapper 路徑,如果你之前在 SpringBoot 啟動類中也使用了 Mapper 掃描注解,需要刪掉

          訪問測試

          編寫兩個簡單的查詢 Controller 然后進(jìn)行訪問測試。

          //?BookController
          @RestController
          public?class?BookController?{

          ????@Autowired
          ????private?BookService?bookService;

          ????@GetMapping(value?=?"/books")
          ????public?Response?selectAll()?throws?Exception?{
          ????????List?books?=?bookService.selectAll();
          ????????return?ResponseUtill.success(books);
          ????}
          }

          //?UserController
          @RestController
          public?class?UserController?{

          ????@Autowired
          ????private?UserService?userService;

          ????@ResponseBody
          ????@GetMapping(value?=?"/users")
          ????public?Response?selectAll()?{
          ????????List?userList?=?userService.selectAll();
          ????????return?ResponseUtill.success(userList);
          ????}
          }

          訪問測試,我這里直接 CURL 請求。

          ???~?curl?localhost:8080/books?
          {
          ??"code":?"0000",
          ??"message":?"success",
          ??"data":?[
          ????{
          ??????"id":?1,
          ??????"author":?"金庸",
          ??????"name":?"笑傲江湖",
          ??????"price":?13,
          ??????"createtime":?"2020-12-19T07:26:51.000+00:00",
          ??????"description":?"武俠小說"
          ????},
          ????{
          ??????"id":?2,
          ??????"author":?"羅貫中",
          ??????"name":?"三國演義",
          ??????"price":?14,
          ??????"createtime":?"2020-12-19T07:28:36.000+00:00",
          ??????"description":?"歷史小說"
          ????}
          ??]
          }
          ???~?curl?localhost:8080/users?
          {
          ??"code":?"0000",
          ??"message":?"success",
          ??"data":?[
          ????{
          ??????"id":?1,
          ??????"name":?"金庸",
          ??????"birthday":?"1924-03-09T16:00:00.000+00:00"
          ????},
          ????{
          ??????"id":?2,
          ??????"name":?"羅貫中",
          ??????"birthday":?"1330-01-09T16:00:00.000+00:00"
          ????}
          ??]
          }
          ???~

          至此,多數(shù)據(jù)源配置完成,測試成功。

          連接池

          其實(shí)在多數(shù)據(jù)源改造中,我們一般情況下都不會使用默認(rèn)的 JDBC 連接方式,往往都需要引入連接池進(jìn)行連接優(yōu)化,不然你可能會經(jīng)常遇到數(shù)據(jù)源連接被斷開等報錯日志。其實(shí)數(shù)據(jù)源切換連接池數(shù)據(jù)源也是十分簡單的,直接引入連接池依賴,然后把創(chuàng)建 dataSource 的部分換成連接池數(shù)據(jù)源創(chuàng)建即可。

          下面以阿里的 Druid 為例,先引入連接池數(shù)據(jù)源依賴。

          <dependency>
          ???<groupId>com.alibabagroupId>
          ???<artifactId>druidartifactId>
          dependency>

          添加 Druid 的一些配置。

          spring.datasource.datasource2.initialSize=3 # 根據(jù)自己情況設(shè)置
          spring.datasource.datasource2.minIdle=3
          spring.datasource.datasource2.maxActive=20

          改寫 dataSource Bean 的創(chuàng)建代碼部分。

          @Value("${spring.datasource.datasource2.jdbc-url}")
          private?String?url;
          @Value("${spring.datasource.datasource2.driver-class-name}")
          private?String?driverClassName;
          @Value("${spring.datasource.datasource2.username}")
          private?String?username;
          @Value("${spring.datasource.datasource2.password}")
          private?String?password;
          @Value("${spring.datasource.datasource2.initialSize}")
          private?int?initialSize;
          @Value("${spring.datasource.datasource2.minIdle}")
          private?int?minIdle;
          @Value("${spring.datasource.datasource2.maxActive}")
          private?int?maxActive;

          @Bean(name?=?"dataSource2")
          public?DataSource?dataSource()?{
          ????DruidDataSource?dataSource?=?new?DruidDataSource();
          ????dataSource.setUrl(url);
          ????dataSource.setDriverClassName(driverClassName);
          ????dataSource.setUsername(username);
          ????dataSource.setPassword(password);
          ????dataSource.setInitialSize(initialSize);
          ????dataSource.setMinIdle(minIdle);
          ????dataSource.setMaxActive(maxActive);
          ????return?dataSource;
          }

          這里只是簡單的提一下使用連接池的重要性,Druid 的詳細(xì)用法還請參考官方文檔。

          文中代碼已經(jīng)上傳到 Github:?

          https://github.com/niumoo/springboot



          推薦閱讀:

          Kafka 精妙的高性能設(shè)計(上篇)

          Kafka 精妙的高性能設(shè)計(下篇)

          面試官:HashMap有幾種遍歷方法?推薦使用哪種?

          如出一轍。。。



          關(guān)互聯(lián)網(wǎng)全棧架構(gòu)

          瀏覽 55
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  性爱激情视频网站 | 无码人妻精品一区二区蜜桃视频 | 免费日本黄色一级片 | 一区二区三区四区无码免费 | 欧美日韩一区二区A片综合 |