Mybatis系列-tkmybatis-08-多数据源配置

    作为一个资深的CRUD工程师,我们在实际使用springboot开发项目的时候,难免会遇到同时使用多个数据库的情况,比如前脚刚查询mysql,后脚就要查询sqlserver。为springboot配置多个数据源,需要用哪个数据库连接,直接@Autowired不就行了。那么问题来了,怎么配置呢?

1、准备工作:

        a、建立了两个数据库,分别名为foodie-shop和foodie-shop-2,foodie-shop包含表users,foodie-shop-2包含表myusers。两表定义完全一致,只是填充的数据有差异。

CREATE TABLE `myusers` (

  `id` varchar(64) NOT NULL COMMENT '主键id 用户id',

  `username` varchar(32) NOT NULL COMMENT '用户名 用户名',

  `password` varchar(64) NOT NULL COMMENT '密码 密码',

  `nickname` varchar(32) DEFAULT NULL COMMENT '昵称 昵称',

  `realname` varchar(128) DEFAULT NULL COMMENT '真实姓名',

  `face` varchar(1024) NOT NULL COMMENT '头像',

  `mobile` varchar(32) DEFAULT NULL COMMENT '手机号 手机号',

  `email` varchar(32) DEFAULT NULL COMMENT '邮箱地址 邮箱地址',

  `sex` int(11) DEFAULT NULL COMMENT '性别 性别 1:男  0:女  2:保密',

  `birthday` date DEFAULT NULL COMMENT '生日 生日',

  `created_time` datetime NOT NULL COMMENT '创建时间 创建时间',

  `updated_time` datetime NOT NULL COMMENT '更新时间 更新时间',

  PRIMARY KEY (`id`)

) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户表 ';





CREATE TABLE `users` (

  `id` varchar(64) NOT NULL COMMENT '主键id 用户id',

  `username` varchar(32) NOT NULL COMMENT '用户名 用户名',

  `password` varchar(64) NOT NULL COMMENT '密码 密码',

  `nickname` varchar(32) DEFAULT NULL COMMENT '昵称 昵称',

  `realname` varchar(128) DEFAULT NULL COMMENT '真实姓名',

  `face` varchar(1024) NOT NULL COMMENT '头像',

  `mobile` varchar(32) DEFAULT NULL COMMENT '手机号 手机号',

  `email` varchar(32) DEFAULT NULL COMMENT '邮箱地址 邮箱地址',

  `sex` int(11) DEFAULT NULL COMMENT '性别 性别 1:男  0:女  2:保密',

  `birthday` date DEFAULT NULL COMMENT '生日 生日',

  `created_time` datetime NOT NULL COMMENT '创建时间 创建时间',

  `updated_time` datetime NOT NULL COMMENT '更新时间 更新时间',

  PRIMARY KEY (`id`)

) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户表 ';

        b、实现通过tkmybatis-generator插件创建了对应的pojo、xml和mapper文件,参考《Mybatis系列-tkmybatis-01-使用tk-mybatis generator 自动生成代码》

2、在application.properties配置两个datasource

        配置application.properties文件。这里两个datasource分别指向不同的数据库。看到这里可能有些疑惑,之前不都是配置的spring.datasource.driver-class-name这种形式吗,这里怎么多了datasource1和datasource3,Spring能自动解析成DataSource吗?答案是不能,这里datasource1和datasource3是自己随便命的数据源的标识,Spring肯定解析不了,继续往后面看。

# tomcat配置

server.port=8080

# datasource配置
spring.datasource.datasource1.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.datasource1.url=jdbc:mysql://127.0.0.1:3306/foodie-shop?useSSL=false&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&serverTimezone=GMT%2B8
spring.datasource.datasource1.username=root
spring.datasource.datasource1.password=123456


spring.datasource.datasource3.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.datasource3.url=jdbc:mysql://127.0.0.1:3306/foodie-shop-2?useSSL=false&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&serverTimezone=GMT%2B8
spring.datasource.datasource3.username=root
spring.datasource.datasource3.password=123456

3、为每个数据源分别创建配置类

    看过《Mybatis系列-tkmybatis源码分析-02-主流程分析》源码分析的应该知道,mybatis初始化的时候需要给每个MapperFactoryBean注入一个SqlSessionTemplate类型的Bean实例。在之前单数据源配置的例子中,我们都是在application.properties文件中配置spring.datasource等属性,以及mybatis的属性,如下所示。Spring会自动读取spring.datasource.*属性创建DataSource,mybatis利用该DataSource,读取mybatis.*的配置,创建SqlSessionTemplate类的Bean实例,供后续mybatis初始化的时候使用。整个过程由tkmybatis自动帮我们完成了,但该方法只能创建一个数据源,不支持多数据源。

# datasource配置
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/foodie-shop?useSSL=false&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&serverTimezone=GMT%2B8&allowMultiQueries=true
spring.datasource.username=root
spring.datasource.password=123456



# TkMybatis配置
## mapper映射文件,配置xml位置接口,mapper类和pojo实体类的位置都可以通过xml文件找到,所以不用配置
mybatis.mapper-locations=classpath*:mapper/*.xml
## 所有POJO类所在包路径
mybatis.type-aliases-package=com.example.demotkmybatisgenerator.pojo

        

    所以在多数据源的配置中,我们并没有配置spring.datasource.*属性以及mybatis.*属性,这时tkmybatis就不能生成有效的SqlSessionTemplate类型的Bean实例。这就需要我们自己为每个数据源创建一个与之对应的SqlSessionTemplate的bean实例,并且在MapperScan中指明,这样在tkmybatis扫描每个mapper类并创建与其对应的mapperFactoryBean的时候,就会为每个mapperFactoryBean指定MapperScan中传入的SqlSessionTemplate实例,从而实现多数据源配置。现在来看看具体例子。

    首先是datasource1对应的配置类。

package com.example.demotkmybatismultidatasource.config;


import org.apache.ibatis.session.SqlSessionFactory;

import org.mybatis.spring.SqlSessionFactoryBean;

import org.mybatis.spring.SqlSessionTemplate;

import org.springframework.beans.factory.annotation.Qualifier;

import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;

import org.springframework.boot.context.properties.ConfigurationProperties;

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 tk.mybatis.spring.annotation.MapperScan;

import javax.sql.DataSource;



/**

* CreateDate: 2021-5-6 <br/>

* Author: dujunlin <br/>

* Description:

* Version: 1.0

**/

@Configuration

//MapperScan需要传入sqlSessionTemplateRef参数(对应配置类bean的名称),这个很重要

@MapperScan(basePackages = "com.example.demotkmybatisgenerator.mapper"

, sqlSessionTemplateRef = "shopSqlSessionTemplate")

public class ShopDataSourceConfig {

    // 注入数据源配置,ConfigurationProperties的作用就是读取spring.datasource.datasource1开头的配置属性,然后将其注入到创建的DataSourceProperties类型

    // 的bean中。Primary是配置bean实例的优先级,有一个配置类中配置就行。

    @Primary

    @Bean

    @ConfigurationProperties(prefix = "spring.datasource.datasource1")

    public DataSourceProperties shopDataSourceProperties() {

        return new DataSourceProperties();

    }



    // 创建数据库连接

    @Primary

    @Bean

    public DataSource shopDataSource(@Qualifier("shopDataSourceProperties") DataSourceProperties dataSourceProperties) {

        return dataSourceProperties.initializeDataSourceBuilder().build();

    }



    // 创建session工厂

    @Primary

    @Bean

    public SqlSessionFactory shopSessionFactory(@Qualifier("shopDataSource") DataSource dataSource) throws Exception {

        SqlSessionFactoryBean sessionFactoryBean = new SqlSessionFactoryBean();

        sessionFactoryBean.setDataSource(dataSource);

        // 配置mapper*.xml位置以及pojo对象的位置

        sessionFactoryBean.setMapperLocations(

                new PathMatchingResourcePatternResolver().getResources("classpath*:mapper/*.xml"));

        sessionFactoryBean.setTypeAliasesPackage("com.example.demotkmybatisgenerator.pojo");

        return sessionFactoryBean.getObject();

    }



    // 创建事务管理(按需添加)

    @Primary

    @Bean

    public DataSourceTransactionManager shopDataSourceTransactionManager(@Qualifier("shopDataSource") DataSource dataSource) {

        return new DataSourceTransactionManager(dataSource);

    }



    // 会话管理

    @Primary

    @Bean

    public SqlSessionTemplate shopSqlSessionTemplate(@Qualifier("shopSessionFactory") SqlSessionFactory sqlSessionFactory) {

        return new SqlSessionTemplate(sqlSessionFactory);

    }

}

 

    然后是datasource3对应的配置类。

package com.example.demotkmybatismultidatasource.config;

import org.apache.ibatis.session.SqlSessionFactory;

import org.mybatis.spring.SqlSessionFactoryBean;

import org.mybatis.spring.SqlSessionTemplate;

import org.springframework.beans.factory.annotation.Qualifier;

import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;

import org.springframework.boot.context.properties.ConfigurationProperties;

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 tk.mybatis.spring.annotation.MapperScan;

import javax.sql.DataSource;



/**

* CreateDate: 2021-5-6 <br/>

* Author: dujunlin <br/>

* Description:

* Version: 1.0

**/

@Configuration

@MapperScan(basePackages = "com.example.demotkmybatisgeneratorthird.mapper"

, sqlSessionTemplateRef = "shop3SqlSessionTemplate")

public class Shop3DataSourceConfig {

    // 注入数据源配置

    @Bean

    @ConfigurationProperties(prefix = "spring.datasource.datasource3")

    public DataSourceProperties shop3DataSourceProperties() {

        return new DataSourceProperties();

    }



    // 创建数据库连接

    @Bean

    public DataSource shop3DataSource(@Qualifier("shop3DataSourceProperties") DataSourceProperties dataSourceProperties) {

        return dataSourceProperties.initializeDataSourceBuilder().build();

    }



    // 创建session工厂

    @Bean

    public SqlSessionFactory shop3SessionFactory(@Qualifier("shop3DataSource") DataSource dataSource) throws Exception {

        SqlSessionFactoryBean sessionFactoryBean = new SqlSessionFactoryBean();

        sessionFactoryBean.setDataSource(dataSource);

        sessionFactoryBean.setMapperLocations(

                new PathMatchingResourcePatternResolver().getResources("classpath*:mapper-third/*.xml"));

        sessionFactoryBean.setTypeAliasesPackage("com.example.demotkmybatisgeneratorthird.pojo");

        return sessionFactoryBean.getObject();

    }



    // 创建事务管理(按需添加)

    @Bean

    public DataSourceTransactionManager shop3DataSourceTransactionManager(@Qualifier("shop3DataSource") DataSource dataSource) {

        return new DataSourceTransactionManager(dataSource);

    }



    // 会话管理

    @Bean

    public SqlSessionTemplate shop3SqlSessionTemplate(@Qualifier("shop3SessionFactory") SqlSessionFactory sqlSessionFactory) {

        return new SqlSessionTemplate(sqlSessionFactory);

    }

}

    至此,多数据源配置完成,后面的操作就跟单数据源一模一样。

注意:

    有个需要注意的是,不同数据库中的表名要保证不一致,因为Spring在管理mapper类的bean实例的时候,实例名称就是mapper类名首字母小写,如果表名一致,Spring中就会存在同名同类型的bean,导致启动失败。

 

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值