【springboot+mybatis】--- springboot + mybatis多数据源配置的正确姿势

源码地址:https://github.com/nieandsun/mybatis-study


1 背景介绍

在真实开发中,一个项目连接多个数据源是常有的事,比如我想查询一个用户的基本简历信息和该用户的工资数据,但是用户表在mybatis-study数据库里,而工资表却在nrsc-mybatis数据库里。假若不考虑使用一个服务调用另一个服务的解决方式,那就需要进行多数据源的操作了。

本文测试数据库和测试表如下:
(1)mybatis-study数据库里有t_user表 ,表中数据如下:
在这里插入图片描述
(2)nrsc-mybatis数据库里有t_salary表 ,表中数据如下:
在这里插入图片描述


2 整体代码结构

整体代码结构如下:
在这里插入图片描述

(1)红色框内为mybatis-study数据库对应的配置
(2)黄色框内为nrsc-mybatis数据库对应的配置

下面对上面的内容进行一一进行讲解。


3 多数据源配置关键代码

springboot和mybatis的整合和spring和mybatis的整合基本一致,主要区别点有两个:

  • springboot下的数据源配置一般都会配置在yml文件里
  • springboot下开启AOP或开启事务的注解一般都会标注在启动类上

其他基本一致。感觉应该比较简单,有不懂或有兴趣的可以clone下来代码看一下,一看肯定就都懂了。不过多解释了,直接上代码。


3.1 yml文件 — 主要是数据源的配置

server:
  port: 9092

# 打印sql语句
logging:
  level:
    com.nrsc.study.mapper : debug
# 数据库1对应的数据源
spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    type: com.alibaba.druid.pool.DruidDataSource
    username: root
    password: 123456
    url: jdbc:mysql://127.0.0.1:3306/mybatis-study?characterEncoding=utf-8&serverTimezone=GMT&useSSL=false
    # 配置内容详解可以看Druid对应的github,这里不过多解释
    # https://github.com/alibaba/druid/wiki/DruidDataSource%E9%85%8D%E7%BD%AE%E5%B1%9E%E6%80%A7%E5%88%97%E8%A1%A8
    filters: stat
    maxActive: 30
    initialSize: 1
    maxWait: 60000
    minIdle: 1
    timeBetweenEvictionRunsMillis: 60000
    minEvictableIdleTimeMillis: 300000
    validationQuery: select 'x'
    testWhileIdle: true
    testOnBorrow: false
    testOnReturn: false
    poolPreparedStatements: true
    maxOpenPreparedStatements: 20
    removeAbandoned: true
    removeAbandonedTimeout: 180

# 数据库2对应的数据源
nrsc:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    type: com.alibaba.druid.pool.DruidDataSource
    username: root
    password: 123456
    url: jdbc:mysql://127.0.0.1:3306/nrsc-mybatis?characterEncoding=utf-8&serverTimezone=GMT&useSSL=false
    # 配置内容详解可以看Druid对应的github,这里不过多解释
    # https://github.com/alibaba/druid/wiki/DruidDataSource%E9%85%8D%E7%BD%AE%E5%B1%9E%E6%80%A7%E5%88%97%E8%A1%A8
    filters: stat
    maxActive: 30
    initialSize: 1
    maxWait: 60000
    minIdle: 1
    timeBetweenEvictionRunsMillis: 60000
    minEvictableIdleTimeMillis: 300000
    validationQuery: select 'x'
    testWhileIdle: true
    testOnBorrow: false
    testOnReturn: false
    poolPreparedStatements: true
    maxOpenPreparedStatements: 20
    removeAbandoned: true
    removeAbandonedTimeout: 180

3.2 多数据源配置文件

3.2.1 mybatis-study数据库对应的配置文件

package com.nrsc.study.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.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;

import javax.sql.DataSource;

/***
 * mybatis-study数据库对应的配置
 *
 * 指定Mapper接口的地址,并指定使用的SqlSessionFactory,可以联系上篇文章思考一下这里的sqlSessionFactoryRef的作用
 */
@MapperScan(basePackages = "com.nrsc.study.mapper.study", sqlSessionFactoryRef = "mybatisStudySqlSessionFactory")
//指定Mapper接口的地址
@Configuration
public class MybatisStudyConfig {

    //创建数据源
    @Bean("mybatisStudyDataSource")
    //以spring.datasource开头的属性都会set到new DruidDataSource()中
    @ConfigurationProperties(prefix = "spring.datasource")
    public DataSource dataSource() {
        return new DruidDataSource();
    }

    //注册事务管理器
    @Bean("mybatisStudyPlatformTransactionManager")
    public PlatformTransactionManager platformTransactionManager() {
        return new DataSourceTransactionManager(dataSource());
    }

    //配置SqlSession工厂
    @Bean("mybatisStudySqlSessionFactory")
    public SqlSessionFactory sqlSessionFactory() throws Exception {
        SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
        //指定数据源
        factoryBean.setDataSource(dataSource());
        //指定所有mapper.xml所在路径
        ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
        factoryBean.setMapperLocations(resolver.getResources("classpath*:mapper/mybatis-study/*.xml"));
        return factoryBean.getObject();
    }
}

3.2.2 nrsc-mybatis数据库对应的配置文件

package com.nrsc.study.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.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;

import javax.sql.DataSource;

/***
 * nrsc-mybatis数据库对应的配置
 *
 * 指定Mapper接口的地址,并指定使用的SqlSessionFactory,可以联系上篇文章思考一下这里的sqlSessionFactoryRef的作用
 */
@MapperScan(basePackages = "com.nrsc.study.mapper.nrsc", sqlSessionFactoryRef = "nrscMybatisSqlSessionFactory")
@Configuration
public class NrscMybatisConfig {

    //创建数据源
    @Bean("nrscMybatisDataSource")
    //以nrsc.datasource开头的属性都会set到new DruidDataSource()中
    @ConfigurationProperties(prefix = "nrsc.datasource")
    public DataSource dataSource() {
        return new DruidDataSource();
    }

    //注册事务管理器
    @Bean("nrscMybatisPlatformTransactionManager")
    public PlatformTransactionManager platformTransactionManager() {
        return new DataSourceTransactionManager(dataSource());
    }

    //配置SqlSession工厂
    @Bean("nrscMybatisSqlSessionFactory")
    public SqlSessionFactory sqlSessionFactory() throws Exception {
        SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
        //指定数据源
        factoryBean.setDataSource(dataSource());
        //指定所有mapper.xml所在路径
        ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
        factoryBean.setMapperLocations(resolver.getResources("classpath*:mapper/nrsc-mybatis/*.xml"));
        return factoryBean.getObject();
    }
}

有兴趣的可以从源码的角度,想一下在@MapperScan注解中加入sqlSessionFactoryRef属性的原因 —
可参考我之前的一篇文章:《【Mybatis+spring整合源码探秘】— 创建Mapper动态代理类核心源码解读》。

当然还应该想一下,为什么mybatis-spring整合源码中在修改Mapper接口的BeanDefinition对象时,为什么将其属性注入方式改完了按照类型注入 ,而不是按照名称注入☺☺☺。


3.3 启动类 — 开启事务往往写在启动类上

package com.nrsc.study;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.transaction.annotation.EnableTransactionManagement;

@SpringBootApplication
@EnableTransactionManagement //开启事务功能
//@EnableAspectJAutoProxy //开启AOP功能
public class MybatisSpringbootApplication {
    public static void main(String[] args) {
        SpringApplication.run(MybatisSpringbootApplication.class, args);
    }
}

4 简单测试

4.1 测试关键代码

这里简单贴一下关键的代码。

4.1.1 controller层代码

@RestController
@RequestMapping("/user")
public class TUserController {

    @Autowired
    private TUserService userService;
    
    @GetMapping(value = "/getUser/{id}", name = "根据id查询用户")
    public UserAndSalaryVO selectByPrimaryKey(@PathVariable("id") Integer id) {
        return userService.selectByPrimaryKey(id);
    }
}

4.1.2 service层代码

@Service
public class TUserServiceImpl implements TUserService {

    @Autowired
    private TUserMapper userMapper;

    @Autowired
    private TSalaryServiceImpl salaryService;

    @Override
    public UserAndSalaryVO selectByPrimaryKey(Integer id) {
        //从mybatis-study数据库里获取用户信息
        TUser user = userMapper.selectByPrimaryKey(id);
        //从nrsc-mybatis数据库里获取用户的工资信息
        TSalary salary = salaryService.selectByUserName(user.getUserName());
        //封装数据并返回
        UserAndSalaryVO VO = new UserAndSalaryVO();
        BeanUtils.copyProperties(user,VO);
        VO.setSalary(salary);
        return VO;
    }
}

4.2 测试结果

测试结果如下:
在这里插入图片描述
可以看到已经获取到了mybatis-study数据库t_user表里的数据和nrsc-mybatis数据库t_salary表里的数据,证明我的多数据源配置已经成功。

发布了193 篇原创文章 · 获赞 198 · 访问量 41万+

猜你喜欢

转载自blog.csdn.net/nrsc272420199/article/details/104001451