iis服务器助手广告广告
返回顶部
首页 > 资讯 > 数据库 >SpringBoot整合多数据源的两种方式
  • 440
分享到

SpringBoot整合多数据源的两种方式

springbootjavamybatismysql面试 2023-09-13 10:09:40 440人浏览 八月长安
摘要

⭐️作者简介:一个力求全干的Java后端开发者。💗个人主页:CVcode码农的博客 👉当前专栏:SpringBoot整合篇✔️本文内容:多数据源的配置,项目中如果需

⭐️作者简介:一个力求全干的Java后端开发者。
💗个人主页:CVcode码农的博客
👉当前专栏:SpringBoot整合篇
✔️本文内容:多数据源的配置,项目中如果需要使用多个数据源,可以直接cv
其他内容查看👇
      SpringBoot整合jdbc和开启事务


本人能力有限,如有遗漏或错误,敬请指正,谢谢

目录

一、学习前提和项目结构

前提:需要掌握mybatis、mybatis-plus的使用和配置

数据库结构:在项目中同时使用这两个数据库

图1 数据库
图2 user表
图3 role表

二、mybatis方式配置多数据源

思路:根据自定义的配置数据源信息初始化数据源【不使用SpringBoot的配置自动注入数据源,因为这样只能配置一个数据源】

<!--druid连接池-->        <dependency>            <groupId>com.alibaba</groupId>            <artifactId>druid-spring-boot-starter</artifactId>            <version>1.1.22</version>        </dependency><!--mybatis-->        <dependency>            <groupId>org.mybatis.spring.boot</groupId>            <artifactId>mybatis-spring-boot-starter</artifactId>            <version>2.3.0</version>        </dependency>

项目结构:
在这里插入图片描述

spring.datasource.db1.username=账号spring.datasource.db1.passWord=密码spring.datasource.db1.driverClassName=com.Mysql.cj.jdbc.Driverspring.datasource.db1.jdbc-url=jdbc:mysql://localhost:3306/db1spring.datasource.db1.type=com.alibaba.druid.pool.DruidDataSourcespring.datasource.db2.username=账号spring.datasource.db2.password=密码spring.datasource.db2.driverClassName=com.mysql.cj.jdbc.Driverspring.datasource.db2.jdbc-url=jdbc:mysql://localhost:3306/db2spring.datasource.db2.type=com.alibaba.druid.pool.DruidDataSource

2.1配置第一个数据源

@Configuration@MapperScan(basePackages = "com.hs.dao.db1",sqlSessionFactoryRef = "db1SqlSessionFactory")public class DataSourceOneConfig {    @Value("${spring.datasource.db1.jdbc-url}")    private String url;    @Value("${spring.datasource.db1.driverClassName}")    private String driverClassName;    @Value("${spring.datasource.db1.username}")    private String username;    @Value("${spring.datasource.db1.password}")    private String password;    //注入db1的数据源    @Bean("db1dataSource")    public DataSource dataSource1(){        DruidDataSource druidDataSource=new DruidDataSource();        druidDataSource.setUsername(username);        druidDataSource.setPassword(password);        druidDataSource.setUrl(url);        druidDataSource.setDriverClassName(driverClassName);        return druidDataSource;    }    //注入由db1数据源的创建的sqlSessionFactory,不懂的可以看mybatis如何和spring整合    @Bean("db1SqlSessionFactory")    public SqlSessionFactory db1SqlSessionFactory(DataSource db1dataSource) throws Exception {        SqlSessionFactoryBean sqlSessionFactoryBean=new SqlSessionFactoryBean();        sqlSessionFactoryBean.setDataSource(db1dataSource);        sqlSessionFactoryBean.setTypeAliasesPackage("com.hs.entity");        org.apache.ibatis.session.Configuration configuration=new org.apache.ibatis.session.Configuration();        configuration.setLogImpl(StdOutImpl.class);        sqlSessionFactoryBean.setConfiguration(configuration);        //扫描mapper的位置        sqlSessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver()                .getResources("classpath*:mapper/db1@Configuration@MapperScan(basePackages = "com.hs.dao.db2",sqlSessionFactoryRef = "db2SqlSessionFactory") //动态代理生成public class DataSourceTwoConfig {    @Value("${spring.datasource.db2.jdbc-url}")    private String url;    @Value("${spring.datasource.db2.driverClassName}")    private String driverClassName;    @Value("${spring.datasource.db2.username}")    private String username;    @Value("${spring.datasource.db2.password}")    private String password;    //注入db2的数据源    @Bean("db2dataSource")    public DataSource dataSource2(){        DruidDataSource druidDataSource=new DruidDataSource();        druidDataSource.setUsername(username);        druidDataSource.setPassword(password);        druidDataSource.setUrl(url);        druidDataSource.setDriverClassName(driverClassName);        return druidDataSource;    }    //注入由db2数据源的创建的sqlSessionFactory,不懂的可以看mybatis如何和spring整合    @Bean("db2SqlSessionFactory")    public SqlSessionFactory db2SqlSessionFactory(DataSource db2dataSource) throws Exception {        SqlSessionFactoryBean sqlSessionFactoryBean=new SqlSessionFactoryBean();        sqlSessionFactoryBean.setDataSource(db2dataSource);        sqlSessionFactoryBean.setTypeAliasesPackage("com.hs.entity");        org.apache.ibatis.session.Configuration configuration=new org.apache.ibatis.session.Configuration();        configuration.setLogImpl(StdOutImpl.class);        sqlSessionFactoryBean.setConfiguration(configuration);        //扫描mapper的位置        sqlSessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver()                .getResources("classpath*:mapper/db2/*.xml"));        return sqlSessionFactoryBean.getObject();    }    //db2数据源的事务管理器    @Bean("db2DataSourceTransactionManager")    public DataSourceTransactionManager db2DataSourceTransactionManager(DataSource db2dataSource){        DataSourceTransactionManager dataSourceTransactionManager=new DataSourceTransactionManager(db2dataSource);        return dataSourceTransactionManager;    }    //这个作用和jdbcTemplate差不多,【但一般不用,可配可不配!】    @Bean    public SqlSessionTemplate db1SqlSessionTemplate(SqlSessionFactory db1SqlSessionFactory){        SqlSessionTemplate sqlSessionTemplate=new SqlSessionTemplate(db1SqlSessionFactory);        return sqlSessionTemplate;    }}

2.3测试查询

(实体类代码省略,代码已通过测试,可自行测试)

//这个由db1数据源动态代理生成beanpublic interface UserMapper {    User getUserById(int id);}//UserMapper.xml<mapper namespace="com.hs.dao.db1.UserMapper">    <select id="getUserById" resultType="com.hs.entity.User">        select * from user where id=#{id}    </select></mapper>
//这个由db2数据源动态代理生成beanpublic interface RoleMapper {    Role getRoleById(int id);}//RoleMapper.xml<mapper namespace="com.hs.dao.db2.RoleMapper">    <select id="getRoleById" resultType="com.hs.entity.Role">        select * from role where id=#{id}    </select></mapper>
@RestControllerpublic class UserController {    @Autowired    private UserMapper userMapper;    @RequestMapping("/user/{id}")    public User getUserById(@PathVariable int id){        User user = userMapper.getUserById(id);        System.out.println(user);        return user;    }}
@RestControllerpublic class RoleController {    @Autowired    private RoleMapper roleMapper;    @RequestMapping("/role/{id}")    public Role getRoleById(@PathVariable int id){        Role role = roleMapper.getRoleById(id);        System.out.println(role);        return role;    }}

三、 mybatis-plus方式配置多数据源

思路:原理使用的是aop,具体实现原理可看我另一篇文章,其他配置可看mybatis-plus官方文档mybatis-plus

ps:以下代码忽略mybatis-plus的mapper

<!--mybatis-plus-->        <dependency>            <groupId>com.baomidou</groupId>            <artifactId>mybatis-plus-boot-starter</artifactId>            <version>3.5.1</version>        </dependency><!--druid-->        <dependency>            <groupId>com.alibaba</groupId>            <artifactId>druid-spring-boot-starter</artifactId>            <version>1.1.22</version>        </dependency><!--多数据源-->        <dependency>            <groupId>com.baomidou</groupId>            <artifactId>dynamic-datasource-spring-boot-starter</artifactId>            <version>3.5.1</version>        </dependency>

项目结构:
在这里插入图片描述

#设置默认的数据源,默认值即为masterspring.datasource.dynamic.primary=master#严格匹配数据源,默认falsetrue:未匹配到指定数据源时抛异常 false:未匹配到则使用默认数据源spring.datasource.dynamic.strict=false spring.datasource.dynamic.datasource.master.url=jdbc:mysql://localhost:3306/db1spring.datasource.dynamic.datasource.master.username=rootspring.datasource.dynamic.datasource.master.password=123456spring.datasource.dynamic.datasource.master.driver-class-name=com.mysql.cj.jdbc.Driver#设置第二个数据源spring.datasource.dynamic.datasource.slave.url=jdbc:mysql://localhost:3306/db2spring.datasource.dynamic.datasource.slave.username=rootspring.datasource.dynamic.datasource.slave.password=123456spring.datasource.dynamic.datasource.slave.driver-class-name=com.mysql.cj.jdbc.Drivermybatis-plus.type-aliases-package=com.hs.entity

3.1快速开始

使用@DS(“库名”) 在方法或者类上切换数据源,如果在方法上没有添加@DS,那么默认在方法中使用的是默认数据源,也就是上面配置spring.datasource.dynamic.primary=master的master数据源

举例1:根据id查询user表数据,user表为db1数据库的一张表,上述配置中的master数据源

@RestControllerpublic class TestController {    @Autowired    private UserMapper userMapper;        //由于没有加@DS,那么使用默认数据源,也可以指定@DS("master")    @RequestMapping("/user/{id}")    public User getUserById(@PathVariable int id){        User user = userMapper.selectById(id);        System.out.println(user);        return user;    }}

举例2:根据id查询role表数据,role表为db2数据库的一张表,上述配置中的slave数据源

@RestControllerpublic class TestController {    @Autowired    private RoleMapper roleMapper;        //指定slave数据源    @DS("slave")    @RequestMapping("/role/{id}")    public Role getRoleById(@PathVariable int id){        Role role = roleMapper.selectById(id);        System.out.println(role);        return role;    }}

举例3:手动切换数据源,在一个方法中,查询两个数据库。根据id查询user表和role表数据

@RestControllerpublic class TestController {    @Autowired    private UserMapper userMapper;    @Autowired    private RoleMapper roleMapper;    @RequestMapping("/test/{id}")    public String getDataById(@PathVariable int id){    //不指定现在默认使用的是master数据源        User user = userMapper.selectById(id);        //该方法作用是切换成slave数据源,只能有一个数据源,如果再添加,会替换之前的数据源        DynamicDataSourceContextHolder.push("slave");        Role role = roleMapper.selectById(id);        System.out.println(user);        System.out.println(role);        //查看当前数据源        System.out.println(DynamicDataSourceContextHolder.peek());        //移除数据源,恢复master数据源        DynamicDataSourceContextHolder.poll();         return "success";    }}

3.2 DynamicDataSourceContextHolder解读

源码得知,内部是由一个ThreadLocal来维护数据源的,也就是说手动切换数据源只在一个线程内有效,如果开一个新线程,那么数据源又变回默认数据源

在这里插入图片描述
验证如下:

@RestControllerpublic class TestController {    @Autowired    private UserMapper userMapper;    @Autowired    private RoleMapper roleMapper;        @RequestMapping("/test")    public String test(){    //使用默认数据源查询        System.out.println(userMapper.selectList(null));        //在当前线程切换到slave数据源        DynamicDataSourceContextHolder.push("slave");                //新启动一个线程,又恢复成默认数据源,role表在slave数据源中,所以此时查询会报错        new Thread(() ->{            System.out.println(roleMapper.selectList(null));        }).start();                return "success";    }}

在这里插入图片描述

四、总述

如果你的项目中使用的是mybatis,那么可以用上面这两种方式来操作多数据源
如果需要自己实现一个,那么需要使用AOP来实现,后续会出一篇文章《AOP动态切换数据源》

五、完整项目地址

完整项目地址

来源地址:https://blog.csdn.net/hongs468/article/details/128469985

您可能感兴趣的文档:

--结束END--

本文标题: SpringBoot整合多数据源的两种方式

本文链接: https://www.lsjlt.com/news/405721.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作