文章目录

  • 概述
  • 思路
  • 步骤
    • Step1 多数据源配置文件applicaiton.yml
    • Step2 初始化多个数据源
    • Step3 配置多个数据源
  • 验证测试
  • 支持事务
    • Step1 配置类中通过@Bean初始化DataSourceTransactionManager
    • Step2 如何使用呢? @Transactional(DataSources.DB1_TRANSACTION)
    • Step3 验证事务
  • 顺便说下 集成JdbcTemplate
    • Step1 配置类中通过@Bean初始化每个数据库实例对应的JdbcTemplate
    • Step2 如何使用呢? @Autowired @Qualifier(DataSources.DB1_JDBCTEMPLATE)
    • Step3 验证
  • 代码

概述

Spring Boot2.x-09 基于Spring Boot + Mybatis使用自定义注解实现数据库切换 通过自定义注解实现了数据库的切库。多数据源的支持我们通过这篇博文来梳理。

单个数据源 见 Spring Boot2.x-07Spring Boot2.1.2整合Mybatis


思路

让不同的数据源绑定不同的mybatis配置,再细化一点就是让不同的数据源扫描不同的包,让不同包下的mapper连接不同的数据源去处理业务逻辑。

多说一句,对于跨库的多表操作,这种整合是支持不了的


步骤

我们基于 Spring Boot2.x-09 基于Spring Boot + Mybatis使用自定义注解实现数据库切换 来改造下,让其支持多数据源。


Step1 多数据源配置文件applicaiton.yml

自定义前缀,在标注了@Configuration的配置类中通过prefix 将数据源关联起来。 这里的配置类为DatasourceConfig。

# datasource  db1   前缀为自定义的datasource-db1
spring:datasource-db1:driver-class-name: com.mysql.cj.jdbc.Driver # JDBC连接Mysql6以上com.mysql.cj.jdbc.Driver (服务端为Mysql8)url: jdbc:mysql://localhost:3306/db1?serverTimezone=UTC&useUnicode=true&characterEncoding=utf8&useSSL=falseusername: rootpassword: root# datasource db2  前缀为自定义的datasource-db2datasource-db2: driver-class-name: com.mysql.cj.jdbc.Driver # JDBC连接Mysql6以上com.mysql.cj.jdbc.Driver  (服务端为Mysql8)url: jdbc:mysql://localhost:3306/db2?serverTimezone=UTC&useUnicode=true&characterEncoding=utf8&useSSL=falseusername: rootpassword: root# mybatis
mybatis_db1: # 映射文件的路径 , 这个切换数据源的场景下不能配置 * 通配符,有多个 逗号隔开,继续跟 classpath:mapper_db1/XXX# 在MybatisConfig.java#sqlSessionFactoryBean方法中通过sqlSessionFactoryBean设置classpath:mapper_db1/*.xml ,不然每次都要改这个地方,不好维护。#  mapper-locations: classpath:mapper_db1/*.xml  # 类型别名包配置,只能指定具体的包,多个配置可以使用英文逗号隔开# 也可以通过sqlSessionFactoryBean.setTypeAliasesPackage("com.artisan.domain.db1")type-aliases-package: com.artisan.domain.db1# Mybatis SQL语句控制台打印configuration: log-impl: org.apache.ibatis.logging.stdout.StdOutImpl# mybatis
mybatis_db2: # 映射文件的路径 , 这个切换数据源的场景下不能配置 * 通配符,有多个 逗号隔开,继续跟 classpath:mapper/XXX# 在MybatisDB2Config.java#sqlSessionFactoryBean方法中通过sqlSessionFactoryBean设置classpath:mapper_db2/*.xml ,不然每次都要改这个地方,不好维护。#mapper-locations: classpath:mapper_db2/*.xml  # 类型别名包配置,只能指定具体的包,多个配置可以使用英文逗号隔开type-aliases-package: com.artisan.domain.db2# Mybatis SQL语句控制台打印configuration: log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

Step2 初始化多个数据源

这里同时也初始化了JdbcTemplate和事务管理,当然了对这个例子是可选操作。 主要是不同DataSource的初始化

多个数据源,操作JdbcTemplate和Transaction,需要指定使用哪个数据源,否则Spring根据type找到多个bean,不知道注入哪个。 【使用@Primary或者@Qualifier都可以】

package com.artisan.config;import javax.sql.DataSource;import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;import com.alibaba.druid.pool.DruidDataSource;@Configuration
public class DatasourceConfig {//destroy-method="close":当数据库连接不使用的时候,将该连接重新放到数据池中@Bean(name=DataSources.DB1,destroyMethod="close")@ConfigurationProperties(prefix = "spring.datasource-db1")public DataSource dataSourceDB1() {// 创建数据源return DataSourceBuilder.create().type(DruidDataSource.class).build();}@Bean(name=DataSources.DB2,destroyMethod="close")@ConfigurationProperties(prefix = "spring.datasource-db2")public DataSource dataSourceDB2() {// 创建数据源return DataSourceBuilder.create().type(DruidDataSource.class).build();}// 支持JdbcTemplate (可选)@Bean(DataSources.DB1_JDBCTEMPLATE)public JdbcTemplate db1JdbcTemplate(@Qualifier(DataSources.DB1) DataSource dataSource) {return new JdbcTemplate(dataSource);}@Bean(DataSources.DB2_JDBCTEMPLATE)public JdbcTemplate db2JdbcTemplate(@Qualifier(DataSources.DB2) DataSource dataSource) {return new JdbcTemplate(dataSource);}// 支持事务(可选)@Bean(DataSources.DB1_TRANSACTION)public DataSourceTransactionManager db1TransactionManager(@Qualifier(DataSources.DB1) DataSource dataSource) {return new DataSourceTransactionManager(dataSource);}@Bean(DataSources.DB2_TRANSACTION)public DataSourceTransactionManager db2TransactionManager(@Qualifier(DataSources.DB2) DataSource dataSource) {return new DataSourceTransactionManager(dataSource);}}

Step3 配置多个数据源

1. 扫描包的路径,不同的数据源扫描的包路径不同
2. 通过@Qualifier指定注入的数据源
3. Mybatis如果使用xml方式,配置文件中有配置项,通过前缀加载对应的配置项

MybatisDB1Config

package com.artisan.config;import javax.sql.DataSource;import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
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;@Configuration
//  db1的接口类的包名
@MapperScan(basePackages = { "com.artisan.dao.db1" }, sqlSessionFactoryRef = "db1SqlSessionFactoryBean")
public class MybatisDB1Config {@Autowired// 必须指定注入哪个数据源,否则找到多个会注入失败@Qualifier(DataSources.DB1)private DataSource db1;@Bean(name = "db1SqlSessionFactoryBean")@ConfigurationProperties(prefix = "mybatis-db1") // 和 配置文件中的前缀保持一致// @Primary 如果SqlSessionFactoryBean的名字和MybatisDB2Config中的一致(默认方法名),需要加上这个注解,优先注入该SqlSessionFactoryBean// 这里我们通过bean指定了name,并且方法名也不一样,所以如果情况不一样,看是否需要加入@Primary 。 如果需要两个方法上加一个就行了,都加的话,spring又找不到bean注入啦。。public SqlSessionFactoryBean db1SqlSessionFactoryBean() throws Exception {SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();// 配置数据源sqlSessionFactoryBean.setDataSource(db1);// 如下的两行代码仅仅用于*.xml文件,如果整个持久层操作没用到xml文件的话,比如使用注解的方式,则无需加// 解决配置到配置文件中通过*配置找不到mapper文件的问题。 如果不设置这一行,在配置文件中,只能使用数组的方式一个个的罗列出来,并且要指定具体的文件名sqlSessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mapper_db1/*.xml"));// 也可以通过在application.yml中配置//sqlSessionFactoryBean.setTypeAliasesPackage("com.artisan.domain.db1");return sqlSessionFactoryBean;}// 可选,如果需要通过SqlSessionTemplate来操作持久层就通过@Bean实例化,我们这个例子中没用到,随手写出来了@Bean(name="db1SqlSessionTemplate")public SqlSessionTemplate db1SqlSessionTemplate() throws Exception {SqlSessionTemplate template = new SqlSessionTemplate(db1SqlSessionFactoryBean().getObject());return template;}}

MybatisDB2Config

package com.artisan.config;import javax.sql.DataSource;import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
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;@Configuration
@MapperScan(basePackages = { "com.artisan.dao.db2" },sqlSessionFactoryRef="db2SqlSessionFactoryBean" ) // 扫描的mybatis接口类的包名
public class MybatisDB2Config {@Autowired// 必须指定注入哪个数据源,否则找到多个会注入失败@Qualifier(DataSources.DB2)private DataSource db2;@Bean(name="db2SqlSessionFactoryBean")@ConfigurationProperties(prefix = "mybatis-db2") // 和 配置文件中的前缀保持一致public SqlSessionFactoryBean db2SqlSessionFactoryBean() throws Exception {SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();// 配置数据源sqlSessionFactoryBean.setDataSource(db2);// 解决配置到配置文件中通过*配置找不到mapper文件的问题。 如果不设置这一行,在配置文件中,只能使用数组的方式一个个的罗列出来,并且要指定具体的文件名sqlSessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mapper_db2/*.xml"));return sqlSessionFactoryBean;}// 可选,如果需要通过SqlSessionTemplate来操作持久层就通过@Bean实例化,我们这个例子中没用到,随手写出来了@Bean(name = "db2SqlSessionTemplate")public SqlSessionTemplate db2SqlSessionTemplate() throws Exception {SqlSessionTemplate template = new SqlSessionTemplate(db2SqlSessionFactoryBean().getObject());return template;}}

验证测试

数据库表、Domain , Dao , Service,Controller中的代码见下面的Github连接,很简单,就不贴了,只说重点

贴下数据库的初始数据吧

db1:

db2:

启动Spring Boot工程,

访问 http://localhost:8080/db1?id=1

访问 http://localhost:8080/db2?id=1


支持事务

Step1 配置类中通过@Bean初始化DataSourceTransactionManager


Step2 如何使用呢? @Transactional(DataSources.DB1_TRANSACTION)


Step3 验证事务

访问: http://localhost:8080/db1/transTest

数据库中的数据

为了方便验证 artisanMapper.updateArtisan(artisan)中故意写错了个字段名,让其抛出异常,测试回滚。 执行方法后,可以看到因为第二个方法报错,第一个方法中的插入的数据也回滚了 。


顺便说下 集成JdbcTemplate

持久层我们这里用的Mybatis,有些同学说我想用JdbcTemplate呢

Step1 配置类中通过@Bean初始化每个数据库实例对应的JdbcTemplate


Step2 如何使用呢? @Autowired @Qualifier(DataSources.DB1_JDBCTEMPLATE)


Step3 验证

启动工程,访问 http://localhost:8080/db1/jdbcTemplateTest

查看数据


代码

https://github.com/yangshangwei/MultiDataSource

Spring Boot2.x-10 基于Spring Boot 2.1.2 + Mybatis 2.0.0实现多数据源,支持事务相关推荐

  1. spring boot+Mybatis+mysql+atomikos+jta实现多数据源分布式事务

    spring boot+Mybatis+mysql+atomikos+jta实现多数据源分布式事务 1.导入相关依赖 2.配置相关application.properties 3.创建配置文件 4.创 ...

  2. Spring Data JPA例子[基于Spring Boot、Mysql]

    关于Spring Data Spring社区的一个顶级工程,主要用于简化数据(关系型&非关系型)访问,如果我们使用Spring Data来开发程序的话,那么可以省去很多低级别的数据访问操作,如 ...

  3. Spring Boot 2.x基础教程:使用JTA实现多数据源的事务管理

    在一个Spring Boot项目中,连接多个数据源还是比较常见的.之前也介绍了如何在几种常用框架的场景下配置多数据源,具体可见: Spring Boot 2.x基础教程:JdbcTemplate的多数 ...

  4. spring配置与监听mysql_spring boot (8)mybatis配置监听,

    我用过两次, 1.一次是数据库以前数据可以为null,现在不想为null,然后不想改代码,所以在插入或修改数据的时候,查一次,把为null的数据变一下,字符串变"",数字变0或-1 ...

  5. 基于Spring Boot+Cloud构建微云架构

    链接:my.oschina.net/u/3636867/blog/1802517 前言 首先,最想说的是,当你要学习一套最新的技术时,官网的英文文档是学习的最佳渠道.因为网上流传的多数资料是官网翻译而 ...

  6. freemarker ftl模板_Spring Boot2 系列教程(十)Spring Boot 整合 Freemarker

    今天来聊聊 Spring Boot 整合 Freemarker. Freemarker 简介 这是一个相当老牌的开源的免费的模版引擎.通过 Freemarker 模版,我们可以将数据渲染成 HTML ...

  7. sku设计mysql_基于spring boot拥有完整sku和下单流程的完全商城

    一个基于spring boot.spring oauth2.0.mybatis.redis的轻量级.前后端分离.防范xss攻击.拥有分布式锁,为生产环境多实例完全准备,数据库为b2b2c设计,拥有完整 ...

  8. 基于spring boot + MybatisPlus 商城管理系统的Java开源商城系统

    前言 Mall4j项目致力于为中小企业打造一个完整.易于维护的开源的电商系统,采用现阶段流行技术实现.后台管理系统包含商品管理.订单管理.运费模板.规格管理.会员管理.运营管理.内容管理.统计报表.权 ...

  9. 基于 Spring Boot + Cloud 构建微云架构

    点击上方"Java基基",选择"设为星标" 做积极的人,而不是积极废人! 源码精品专栏 原创 | Java 2019 超神之路,很肝~ 中文详细注释的开源项目 ...

  10. 基于Spring Boot+Cloud构建微云架构。

    前言 首先,最想说的是,当你要学习一套最新的技术时,官网的英文文档是学习的最佳渠道.因为网上流传的多数资料是官网翻译而来,很多描述的重点也都偏向于作者自身碰到的问题,这样就很容易让你理解和操作出现偏差 ...

最新文章

  1. 2021年大数据Spark(四十八):Structured Streaming 输出终端/位置
  2. java spring cloud版b2b2c社交电商spring cloud分布式微服务:分布式配置中心
  3. 软件工程作业----个人读后感
  4. STM32F10x之RCC
  5. linux嵌入式c网络编程,嵌入式Linux网络编程之:网络高级编程
  6. 课时20:内嵌函数和闭包
  7. linux怎么使多条命令同时执行
  8. Android 使用ViewPager实现view轮播效果,单个item分页样式,多个item分页样式,横向listview
  9. 【百度地图API】如何批量转换为百度经纬度
  10. .NET技术面试题系列(2) -sql server数据库优化规范
  11. mysql slave_mysql master slave
  12. Wi-Fi 联盟撤销华为资格;华为已熟练掌握 ARM 架构修改;苹果 2020 年或推 5G 手机 | 极客头条...
  13. java 日期 年数_关于java:为什么不赞成使用“新日期(整数年,整数月,整数日)”?...
  14. vwmare 15“无权输入许可证密钥...”与出现新问题hadoop集群无法启动
  15. SpringBoot版本升级
  16. Linux账户设置能su不能ssh,ssh无法登录可以su切换的问题
  17. 用unity制作2d钟表
  18. Probably Approximately Correct learning framework
  19. 张亚飞《.Net for Flash FMS》读后笔记一
  20. 熊掌号周级推送php教程,浅析,熊掌号:实时、小时、天级、周级收录!

热门文章

  1. loam_livox
  2. html 入门例子(二) 折行
  3. mysql读取表最后10条数据
  4. Leetcode 58.最后一个单词的长度 (每日一题 20210705)
  5. 深度学习基础知识(一): 概述-神经网络起源和发展
  6. 报错整理:ImportError: cannot import name ‘mean_absolute_percentage_error‘ from ‘sklearn.metrics‘
  7. mysql语句导出数据库文件_通过Mysql命令行语句来导入、导出数据库文件
  8. Pandas读取中文文本文件报错:python ‘utf-8‘ codec can‘t decode byte 0xe3 in position 0: unexpected end of data
  9. Online Learning场景下实时新闻热点机器学习训练实践
  10. 【机器学习PAI实践十】深度学习Caffe框架实现图像分类的模型训练