第007课:Spring Boot MyBatis Druid 多数据源配置

1. Druid介绍

  • Druid 是阿里巴巴开源平台上的一个项目,整个项目由数据库连接池、插件框架和 SQL 解析器组成。该项目主要是为了扩展 JDBC 的一些限制,可以让程序员实现一些特殊的需求,比如向密钥服务请求凭证、统计 SQL 信息、SQL 性能收集、SQL 注入检查、SQL 翻译等,程序员可以通过定制来实现自己需要的功能。

  • Druid 首先是一个数据库连接池,但它不仅仅是一个数据库连接池,它还包含一个 ProxyDriver,一系列内置的 JDBC 组件库,一个 SQL Parser。在 Javad 的世界中 Druid 是目前最好的数据库连接池,在功能、性能、扩展性方面,都超过其他数据库连接池,包括 DBCP、C3P0、BoneCP、Proxool、JBoss DataSource。

2. 多数据源应用场景

目前,业界流行的数据操作框架是 Mybatis,那 Druid 是什么呢?Druid 是 Java 的数据库连接池组件。Druid 能够提供强大的监控和扩展功能。比如可以监控 SQL ,在监控业务可以查询慢查询 SQL 列表等。

Druid 核心主要包括三部分:

  • DruidDriver 代理 Driver,能够提供基于 Filter-Chain 模式的插件体系。

  • DruidDataSource 高效可管理的数据库连接池

  • SQLParser 当业务数据量达到了一定程度,DBA 需要合理配置数据库资源。即配置主库的机器-高配置,把核心高频的数据放在主库上;把次要的数据放在从库-低配置。开源节流嘛,就这个意思。把数据放在不同的数据库里,就需要通过不同的数据源进行操作数据。

实例:user 用户表在主库 master 上,地址表 city 在从库 cluster 上。下面实现获取,根据用户名获取用户信息,包括从库的地址信息,那么需要从主库和从库中分别获取数据,并在业务逻辑层组装返回。

3. 建表

主表

DROP TABLE IF EXISTS `user`;
CREATE TABLE user
(
id INT(10) unsigned PRIMARY KEY NOT NULL COMMENT '用户编号' AUTO_INCREMENT,
user_name VARCHAR(25) COMMENT '用户名称',
description VARCHAR(25) COMMENT '描述'
)ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
-- 插入数据
INSERT user VALUES (1 ,'博闻','微信公众号【猿码天地】');

从表

DROP TABLE IF EXISTS `city`;
CREATE TABLE `city` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '城市编号',
`province_id` int(10) unsigned NOT NULL COMMENT '省份编号',
`city_name` varchar(25) DEFAULT NULL COMMENT '城市名称',
`description` varchar(25) DEFAULT NULL COMMENT '描述',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
-- 插入数据
INSERT city VALUES (1 ,1001,'深圳市','猿码天地');

4. 项目结构

com.bowen.config - 配置层(数据源配置)
com.bowen.controller - Controller层
com.bowen.dao - 数据操作层DAO
com.bowen.domain - 实体类
com.bowen..service - 业务逻辑层
SrpingbootDruidApplication - 应用启动类
application.properties - 应用配置文件,应用启动会自动读取配置。

5. 详细配置说明

5.1 依赖引入

需要引入Spring Boot Mybatis 依赖、MySQL 连接驱动依赖、Druid 数据连接池依赖等。



    4.0.0

    com.bowen
    srpingboot-druid
    0.0.1-SNAPSHOT
    jar

    srpingboot-druid
    Demo project for Spring Boot

    
    
        org.springframework.boot
        spring-boot-starter-parent
        2.3.1.RELEASE
        
        
    

    
        UTF-8
        UTF-8
        1.8
        1.2.0
        5.1.39
        1.0.18
    

    
        
        
            org.springframework.boot
            spring-boot-starter-web
        

        
        
            org.mybatis.spring.boot
            mybatis-spring-boot-starter
            ${mybatis-spring-boot}
        

        
        
            mysql
            mysql-connector-java
            ${mysql-connector}
        

        
        
            com.alibaba
            druid
            ${druid}
        

        
        
            junit
            junit
            4.12
        

        
        
            org.springframework.boot
            spring-boot-starter-test
            test
        
    


5.2 application配置文件

分别配置了master 数据源和cluster 数据源。

## master 数据源配置
master.datasource.url=jdbc:mysql://localhost:3306/db_druid1?useUnicode=true&characterEncoding=utf8
master.datasource.username=root
master.datasource.password=123456
master.datasource.driverClassName=com.mysql.jdbc.Driver

## cluster 数据源配置
cluster.datasource.url=jdbc:mysql://localhost:3306/db_druid2?useUnicode=true&characterEncoding=utf8
cluster.datasource.username=root
cluster.datasource.password=123456
cluster.datasource.driverClassName=com.mysql.jdbc.Driver

5.3 数据源配置

多数据源配置的时候,必须要有一个主数据源,即 MasterDataSourceConfig 配置:

package com.bowen.config;

import com.alibaba.druid.pool.DruidDataSource;
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.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;

import javax.sql.DataSource;

@Configuration
// 扫描 Mapper 接口并容器管理
@MapperScan(basePackages = MasterDataSourceConfig.PACKAGE, sqlSessionFactoryRef = "masterSqlSessionFactory")
public class MasterDataSourceConfig {

    // 精确到 master 目录,以便跟其他数据源隔离
    static final String PACKAGE = "com.bowen.dao.master";
    static final String MAPPER_LOCATION = "classpath:mapper/master/*.xml";

    @Value("${master.datasource.url}")
    private String url;

    @Value("${master.datasource.username}")
    private String user;

    @Value("${master.datasource.password}")
    private String password;

    @Value("${master.datasource.driverClassName}")
    private String driverClass;

    @Bean(name = "masterDataSource")
    @Primary
    public DataSource masterDataSource() {
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setDriverClassName(driverClass);
        dataSource.setUrl(url);
        dataSource.setUsername(user);
        dataSource.setPassword(password);
        return dataSource;
    }

    @Bean(name = "masterTransactionManager")
    @Primary
    public DataSourceTransactionManager masterTransactionManager() {
        return new DataSourceTransactionManager(masterDataSource());
    }

    @Bean(name = "masterSqlSessionFactory")
    @Primary
    public SqlSessionFactory masterSqlSessionFactory(@Qualifier("masterDataSource") DataSource masterDataSource)
            throws Exception {
        final SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
        sessionFactory.setDataSource(masterDataSource);
        sessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver()
                .getResources(MasterDataSourceConfig.MAPPER_LOCATION));
        return sessionFactory.getObject();
    }

@Primary 标志这个 Bean 如果在多个同类 Bean 候选时,该 Bean 优先被考虑。「多数据源配置的时候注意,必须要有一个主数据源,用 @Primary 标志该 Bean」
@MapperScan 扫描 Mapper 接口并给容器管理,包路径精确到 master,为了和下面 cluster 数据源做到精确区分。
@Value 获取全局配置文件 application.properties 的 kv 配置,并自动装配。
sqlSessionFactoryRef 表示定义了 key ,表示一个唯一 SqlSessionFactory 实例。

从数据源 ClusterDataSourceConfig 配置如下:

package com.bowen.config;

import com.alibaba.druid.pool.DruidDataSource;
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.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;

import javax.sql.DataSource;

@Configuration
// 扫描 Mapper 接口并容器管理
@MapperScan(basePackages = ClusterDataSourceConfig.PACKAGE, sqlSessionFactoryRef = "clusterSqlSessionFactory")
public class ClusterDataSourceConfig {

    // 精确到 cluster 目录,以便跟其他数据源隔离
    static final String PACKAGE = "com.bowen.dao.cluster";
    static final String MAPPER_LOCATION = "classpath:mapper/cluster/*.xml";

    @Value("${cluster.datasource.url}")
    private String url;

    @Value("${cluster.datasource.username}")
    private String user;

    @Value("${cluster.datasource.password}")
    private String password;

    @Value("${cluster.datasource.driverClassName}")
    private String driverClass;

    @Bean(name = "clusterDataSource")
    public DataSource clusterDataSource() {
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setDriverClassName(driverClass);
        dataSource.setUrl(url);
        dataSource.setUsername(user);
        dataSource.setPassword(password);
        return dataSource;
    }

    @Bean(name = "clusterTransactionManager")
    public DataSourceTransactionManager clusterTransactionManager() {
        return new DataSourceTransactionManager(clusterDataSource());
    }

    @Bean(name = "clusterSqlSessionFactory")
    public SqlSessionFactory clusterSqlSessionFactory(@Qualifier("clusterDataSource") DataSource clusterDataSource)
            throws Exception {
        final SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
        sessionFactory.setDataSource(clusterDataSource);
        sessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver()
                .getResources(ClusterDataSourceConfig.MAPPER_LOCATION));
        return sessionFactory.getObject();
    }
}

上面数据配置分别扫描 Mapper 接口,com.bowen.dao.master(对应 xml classpath:mapper/master ) 和 com.bowen.dao.cluster(对应 xml classpath:mapper/cluster ) 包中对应的 UserDAO 和 CityDAO 。都有 @Mapper 标志为 Mybatis 的并通过容器管理的 Bean。Mybatis 内部会使用反射机制运行去解析相应 SQL。

5.4 业务层

业务层 biz 注入了两个 DAO,不用关心和指定到具体说明数据源。

package com.bowen.service.impl;

import com.bowen.dao.cluster.CityDao;
import com.bowen.dao.master.UserDao;
import com.bowen.domain.City;
import com.bowen.domain.User;
import com.bowen.service.UserService;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;

/**
 * 用户业务实现层
 */
@Service
public class UserServiceImpl implements UserService {

    /**
     * 主数据源
     */
    @Resource
    private UserDao userDao;

    /**
     * 从数据源
     */
    @Resource
    private CityDao cityDao;

    @Override
    public User findByName(String userName) {
        User user = userDao.findByName(userName);
        City city = cityDao.findByName("深圳市");
        user.setCity(city);
        return user;
    }
}

6. 运行

启动工程,浏览器输入:http://localhost:8091/test/api/user?userName=博闻
结果:

第007课:Spring Boot MyBatis Druid 多数据源配置_第1张图片
 

这里 city 结果体来自 cluster 库,user 结果体来自 master 库,达到了多数据源配置获取数据的目的。

7. 总结

Druid 是一款非常优秀的数据库连接池开源软件,使用 Druid 提供的druid-spring-boot-starter可以非常简单的对 Druid 进行集成。

Druid 提供了很多预置的功能,非常方便对 SQL 进行监控、分析。在集成多数据源的时候,我们配置不同数据源,采用一层一层注入的形式,最终构建出对应的SqlSessionTemplate,并将其注入到对应的 Mapper 包中来使用。

利用 Druid 属性继承的功能,可以简化多数据源的配置,MyBatis+Druid 的多数据源解决方案很简单高效。

多数据源适合的场景很多。不同的 DataSource ,不同的 SqlSessionFactory 和 不同的 DAO 层,在业务逻辑层做整合。总体的架构图如下:

第007课:Spring Boot MyBatis Druid 多数据源配置_第2张图片

源码下载地址:关注公众号【猿码天地】并回复 springboot 获取

 

文章推荐

Java泛型详解,必须掌握

第004课:Spring Boot 项目属性配置

第005课:Spring Boot 中MVC支持

第003课:Spring Boot 快速体验 Web 开发

Maven 的这 7 个问题你思考过没有?

你可以不尊重我的人,但必须尊重我的代码...

第001课:Spring Boot 课程概览

第002课:Spring Boot 开发环境搭建

50份Java优秀求职者简历

 

扫描二维码关注公众号 : 猿码天地

你多学一样本事,就少说一句求人的话,现在的努力,是为了以后的不求别人,实力是最强的底气。记住,活着不是靠泪水博得同情,而是靠汗水赢得掌声。

——《写给程序员朋友》

你可能感兴趣的:(springboot实战)