关于springboot:SpringBoot-的多数据源配置

42次阅读

共计 8626 个字符,预计需要花费 22 分钟才能阅读完成。

最近在我的项目开发中,须要为一个应用 MySQL 数据库的 SpringBoot 我的项目,新增加一个 PLSQL 数据库数据源,那么就须要进行 SpringBoot 的多数据源开发。代码很简略,上面是实现的过程。

<!– more –>

环境筹备

试验环境:

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

因为我本地只有 MySQL 数据库,为了不便演示,我会在启动一个本地 MySQL,在 MySQL 创立两个数据库,每个库中均有一个表,以此进行演示。

数据筹备

本地 MySQL 端口默认不做改变,端口号 3306。

创立数据库 demo1,demo2。在 demo1 数据库中创立表 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 数据库中创立表 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');

数据筹备结束,表中都新增了两条数据。

我的项目筹备

这里间接从 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

如果你手上曾经有了一个 SpringBoot 我的项目,既然你想革新成多数据源,那么你应该曾经有了一个数据源了,如果新增的数据源数据库和目前的统一,你能够间接应用你的我的项目进行革新测试。

多数据源

SpringBoot 的多数据源开发非常简略,如果多个数据源的数据库雷同,比方都是 MySQL,那么依赖是不须要任何改变的,只须要进行多数据源配置即可。

如果你新增的数据库数据源和目前的数据库不同,记得引入新数据库的驱动依赖,比方 MySQL 和 PGSQL。

<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <scope>runtime</scope>
</dependency>

<dependency>
    <groupId>org.postgresql</groupId>
    <artifactId>postgresql</artifactId>
    <version>42.2.7</version>
</dependency>

连贯配置

既然有多个数据源,因为数据库用户名明码可能不雷同,所以是须要配置多个数据源信息的,间接在 properties/yml 中配置即可。这里要留神依据配置的属性名进行辨别,同时因为数据源要有一个默认应用的数据源,最好在名称上有所辨别(这里应用 primary 作为主数据源标识)。

########################## 主数据源 ##################################
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=

########################## 第二个数据源 ###############################
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

留神,配置中的数据源连贯 url 开端应用的是 jdbc-url.

因为应用了 Mybatis 框架,所以 Mybatis 框架的配置信息也是少不了的,指定扫描目录 mapper 下的mapper xml 配置文件。

Mybatis 配置

如何编写 Mybatis Mapper 或者如何应用工具生成 Mybatis Mapper 不是本文的重点,如果你不晓得能够参考 Mybatis 官网文档或者我之前的文章。

链接一:应用 Mybatis(主动生成插件)拜访数据库

链接二:应用 Mybatis 集成 pagehelper 分页插件和 mapper 插件

上面我曾经依照下面的两个库中的两个表,Book 和 User 表别离编写相应的 Mybatis 配置。

创立 BookMapper.xmlUserMapper.xml 放到配置文件配置的门路 mapper 目录下。创立 UserMapper 和 BookMapper 接口操作类放在不同的目录。这里留神 Mapper 接口要按数据源离开放在不同的目录中。后续好应用不同的数据源配置扫描不同的目录,这样就能够实现不同的 Mapper 应用不同的数据源配置。

Service 层没有变动,这里 BookMapper 和 UserMapper 都有一个 selectAll() 办法用于查问测试。

多数据源配置

下面你应该看到了,到目前为止和 Mybatis 单数据源写法惟一的区别就是 Mapper 接口应用不同的目录离开了,那么这个不同点肯定会在数据源配置中体现。

主数据源

开始配置两个数据源信息,先配置主数据源,配置扫描的 MapperScan 目录为 com.wdbyte.mapper.primary

/**
 * 主数据源配置
 *
 * @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);
    }
}

和单数据源不同的是这里把

  • dataSource
  • sqlSessionFactory
  • transactionManager
  • sqlSessionTemplate

都独自进行了配置,简略的 bean 创立,上面是用到的一些注解阐明。

  • @ConfigurationProperties(prefix = "spring.datasource.primary"):应用 spring.datasource.primary 结尾的配置。
  • @Primary:申明这是一个主数据源(默认数据源),多数据源配置时 必不可少
  • @Qualifier:显式抉择传入的 Bean。

第二个数据源

第二个数据源和主数据源惟一不同的只是 MapperScan 扫描门路和创立的 Bean 名称,同时没有 @Primary 主数据源的注解。

/**
 * 第二个数据源配置
 * 
 * @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);
    }
}

留神:因为曾经在两个数据源中别离配置了扫描的 Mapper 门路,如果你之前在 SpringBoot 启动类中也应用了 Mapper 扫描注解,须要删掉

拜访测试

编写两个简略的查问 Controller 而后进行拜访测试。

// BookController
@RestController
public class BookController {

    @Autowired
    private BookService bookService;

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

// UserController
@RestController
public class UserController {

    @Autowired
    private UserService userService;

    @ResponseBody
    @GetMapping(value = "/users")
    public Response selectAll() {List<User> 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"
    }
  ]
}
➜  ~

至此,多数据源配置实现,测试胜利。

连接池

其实在多数据源革新中,咱们个别状况下都不会应用默认的 JDBC 连贯形式,往往都须要引入连接池进行连贯优化,不然你可能会常常遇到数据源连贯被断开等报错日志。其实数据源切换连接池数据源也是非常简略的,间接引入连接池依赖,而后把创立 dataSource 的局部换成连接池数据源创立即可。

上面以阿里的 Druid 为例,先引入连接池数据源依赖。

<dependency>
   <groupId>com.alibaba</groupId>
   <artifactId>druid</artifactId>
</dependency>

增加 Druid 的一些配置。

spring.datasource.datasource2.initialSize=3 # 依据本人状况设置
spring.datasource.datasource2.minIdle=3
spring.datasource.datasource2.maxActive=20

改写 dataSource Bean 的创立代码局部。

@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 的具体用法还请参考官网文档。

文中代码曾经上传到 Github: https://github.com/niumoo/springboot

最初的话

文章有帮忙能够点个「」或「 分享 」,都是反对!
文章每周继续更新,能够关注「未读代码」公众号或者我的博客。

正文完
 0