【SpringBoot整合系列】SpringBoot配置多数据源

背景

  • 在单数据源的情况下,Spring Boot的配置非常简单,只需要在application.properties文件中配置连接参数即可。
  • 但是往往随着业务量发展,我们通常会进行数据库拆分或是引入其他数据库,从而我们需要配置多个数据源

技术选型

  • SpringBoot2.3.12
  • jdk1.8
  • mysql5.7
  • 持久层框架mybatis

配置多数据源思路(以两个为例)

  1. 要执行两个数据库的操作,就需要有两个数据库配置
  2. 有两个数据库配置那就要两个SqlSessionBuilder来创建SqlSessionFactory
  3. 有两个SqlSessionFactory就能创建两个数据库自己的sqlSession
  4. 然后就能执行不同数据库的操作了
  5. 现在用的都是数据库连接池,需要创建dataSource,因此,按照上面的思路,也需要有各自数据库的dataSource
  6. 用各自的dataSource创建各自的SqlSessionFactory
  7. 继而创建各自的SqlSessionTemplate
  8. 当然,事务管理器也应该是用各自的dataSource来创建
  9. 那么,各自的SqlSessionFactory就要扫描各自的mapper层,因此就需要有各自的mapper包
  10. 至于各自的mapper.xml可以放在一起,也可以不放在一起,因为mapper.xml中的namespace是根据包名来映射的

代码实现

1.导入依赖

		<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-logging</artifactId>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.21</version>
        </dependency>
        <!-- 阿里数据库连接池 -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.0.9</version>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.3.1</version>
        </dependency>

2.各自的配置

server:
  port: 8888

logging:
  level:
      org.springframework.web: debug
      com.kgc.mapper: debug
spring:
  datasource:
    smbms:
      driverClassName: com.mysql.cj.jdbc.Driver
      url: jdbc:mysql://localhost:3306/smbms?useSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai
      username: root
      password: 123456
    news:
      driverClassName: com.mysql.cj.jdbc.Driver
      url: jdbc:mysql://localhost:3306/chinanewsdb?useSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai
      username: root
      password: 123456

mybatis:
  mapper-locations: classpath:mybatis/mapper/*.xml
  type-aliases-package: com.kgc.pojo
  news:
    mapper-locations: classpath:mybatis/newsmapper/*.xml
#  configuration:
#    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

在这里插入图片描述

3.各自的dataSource

news数据库的

package com.kgc.config;

import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.beans.factory.annotation.Value;
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 javax.sql.DataSource;

/**
 * @author: zjl
 * @datetime: 2024/4/20
 * @desc:
 */
@Configuration
//@ConfigurationProperties(prefix = "spring.datasource.news")
public class NewsDataSourceConfig {
    @Value("${spring.datasource.news.driverClassName}")
    private String driverClassName;
    @Value("${spring.datasource.news.url}")
    private String url;
    @Value("${spring.datasource.news.username}")
    private String username;
    @Value("${spring.datasource.news.password}")
    private String password;

    @Bean("newsDataSource")
    public DataSource createDataSource() {
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setDriverClassName(driverClassName);
        dataSource.setUrl(url);
        dataSource.setUsername(username);
        dataSource.setPassword(password);
        return dataSource;
    }
}

smbms数据库的

package com.kgc.config;

import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.beans.factory.annotation.Value;
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 javax.sql.DataSource;

/**
 * @author: zjl
 * @datetime: 2024/4/20
 * @desc:
 */
@Configuration
//@ConfigurationProperties(prefix = "spring.datasource.smbms")
public class SmbmsDataSourceConfig {
    @Value("${spring.datasource.smbms.driverClassName}")
    private String driverClassName;
    @Value("${spring.datasource.smbms.url}")
    private String url;
    @Value("${spring.datasource.smbms.username}")
    private String username;
    @Value("${spring.datasource.smbms.password}")
    private String password;

    @Bean("smbmsDataSource")
    @Primary
    public DataSource createDataSource() {
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setDriverClassName(driverClassName);
        dataSource.setUrl(url);
        dataSource.setUsername(username);
        dataSource.setPassword(password);
        return dataSource;
    }
}

注意:@Primary注解

  • 其作用与功能,当有多个相同类型的bean时,使用@Primary来赋予bean更高的优先级。
  • 在这里,需要注册多个相同DataSource类型的bean,要有一个有更高的优先级,否则会报错

4.各自的SqlSessionFactory等

news数据库的

package com.kgc.config;

import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
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 org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import javax.annotation.Resource;
import javax.sql.DataSource;

/**
 * @author: zjl
 * @datetime: 2024/4/20
 * @desc:
 */
@Configuration
@EnableTransactionManagement
@MapperScan(value = "com.kgc.news.mapper",sqlSessionFactoryRef = "newsSqlSessionFactory")
public class NewsSqlSessionFactoryConfiguratiion {
    @Resource(name = "newsDataSource")
    private DataSource newsDataSource;
    @Value("${mybatis.news.mapper-locations}")
    private String mapperLocations;
    @Bean("newsSqlSessionFactory")
    public SqlSessionFactory create() throws Exception {
        SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
        bean.setDataSource(newsDataSource);
        PathMatchingResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();
        bean.setMapperLocations(resourcePatternResolver.getResources(mapperLocations));
        return bean.getObject();
    }

    @Bean("newsSqlSessionTemplate")
    public SqlSessionTemplate createSqlSession(@Qualifier("newsSqlSessionFactory") SqlSessionFactory sqlSessionFactory){
        return new SqlSessionTemplate(sqlSessionFactory);
    }

    @Bean("newsTransactionManager")
    public PlatformTransactionManager createTransactionManager(){
        return new DataSourceTransactionManager(newsDataSource);
    }
}

smbms数据库的

package com.kgc.config;

import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
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 org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import javax.annotation.Resource;
import javax.sql.DataSource;
import java.io.IOException;

/**
 * @author: zjl
 * @datetime: 2024/4/20
 * @desc:
 */
@Configuration
@EnableTransactionManagement
@MapperScan(value = "com.kgc.mapper",sqlSessionFactoryRef = "smbmsSqlSessionFactory")
public class SmbmsSqlSessionFactoryConfiguratiion {
    @Resource(name = "smbmsDataSource")
    private DataSource smbmsDataSource;
    @Value("${mybatis.mapper-locations}")
    private String mapperLocations;
    @Bean("smbmsSqlSessionFactory")
    public SqlSessionFactory create() throws Exception {
        SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
        bean.setDataSource(smbmsDataSource);
        PathMatchingResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();
        bean.setMapperLocations(resourcePatternResolver.getResources(mapperLocations));
        return bean.getObject();
    }

    @Bean("smbmsSqlSessionTemplate")
    public SqlSessionTemplate createSqlSession(@Qualifier("smbmsSqlSessionFactory") SqlSessionFactory sqlSessionFactory){
        return new SqlSessionTemplate(sqlSessionFactory);
    }

    @Bean("smbmsTransactionManager")
    public PlatformTransactionManager createTransactionManager(){
        return new DataSourceTransactionManager(smbmsDataSource);
    }
}

5.去掉启动类头上的@MapperScan

@SpringBootApplication
//@MapperScan(basePackages = {"com.kgc.mapper"})
public class BootdemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(BootdemoApplication.class, args);
    }
}

6.各自的mapper接口

在这里插入图片描述

public interface UserMapper {
    int selectCount();
}
public interface NewsMapper {
    int selectCount();
}

7.各自的mapper.xml

在这里插入图片描述

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.kgc.mapper.UserMapper">
    <select id="selectCount" resultType="int">
        SELECT COUNT(1) FROM SMBMS_USER
    </select>
</mapper>
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.kgc.news.mapper.NewsMapper">
    <select id="selectCount" resultType="int">
        SELECT COUNT(1) FROM news_detail
    </select>
</mapper>

8.测试

service

@Service
public class UserService {
    @Resource
    private UserMapper userMapper;
    @Resource
    private NewsMapper newsMapper;

    public Integer allCount(){
        return userMapper.selectCount() + newsMapper.selectCount();
    }
}

controller

@RestController
public class UserController {
    @Resource
    private UserService userService;

    @RequestMapping("/all")
    public Object all(){
        return userService.allCount();
    }
}

相关推荐

  1. SpringBoot整合Mybatis实现数据配置

    2024-04-24 12:14:03       12 阅读
  2. Springboot实现配置数据

    2024-04-24 12:14:03       39 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-04-24 12:14:03       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-04-24 12:14:03       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-04-24 12:14:03       18 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-04-24 12:14:03       20 阅读

热门阅读

  1. C++中的抽象类

    2024-04-24 12:14:03       16 阅读
  2. draw.io使用心得

    2024-04-24 12:14:03       14 阅读
  3. draw.io使用心得

    2024-04-24 12:14:03       14 阅读
  4. Hibernate6根据xml获取ddl sql语句

    2024-04-24 12:14:03       10 阅读
  5. Node.js 环境变量动态获取和静态获取的区别

    2024-04-24 12:14:03       12 阅读
  6. go实现异常捕捉

    2024-04-24 12:14:03       12 阅读
  7. 详细解读DreamFusion

    2024-04-24 12:14:03       13 阅读
  8. 使用 torchtune 微调 Llama3

    2024-04-24 12:14:03       17 阅读
  9. 【Nginx】MACOS 安装与部署

    2024-04-24 12:14:03       17 阅读