SpringBoot+Mybatis实现多数据源+分页

news2025/3/14 1:45:24

1 主要依赖版本

(1)SpringBoot 2.7.8

(2)Mybatis 2.2.2

(3)Pagehelper 1.3.0

(4)MySQL 8.0.26

(5)Oracle 11.2.0.3

2 概述

(1)这里使用两个数据源,分别是MySQL和Oracle,配置两个数据库;

(2)针对以上数据源分别配置Mybatis和Pagehelper(实现分页);

(3)数据源、Mybatis、分页都自定义配置,在启动类关闭它们的自动配置。

3 SpringBoot整合Mybatis实现多数据源动态切换

3.1 整合与配置

3.1.1 相关依赖pom.xml

<!-- mybatis-spring-boot-starter -->
<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>2.2.2</version>
</dependency>
<!-- pagehelper-spring-boot-starter -->
<dependency>
    <groupId>com.github.pagehelper</groupId>
    <artifactId>pagehelper-spring-boot-starter</artifactId>
    <version>1.3.0</version>
</dependency>
<!-- mysql -->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.26</version>
    <scope>runtime</scope>
</dependency>
<!-- oracle -->
<dependency>
    <groupId>com.oracle</groupId>
    <artifactId>ojdbc6</artifactId>
    <version>11.2.0.3</version>
</dependency>
<!-- hutool -->
<dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-all</artifactId>
    <version>5.7.22</version>
</dependency>
<!-- yml文件自定义配置,输入提示-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-configuration-processor</artifactId>
    <optional>true</optional>
</dependency>

3.1.2 application.yml配置

        yml配置中配置了db1和db2两个数据源以及分页,db1对应MySQL,db2对应Oracle,如果不需要分页这里可以省去spring.pagehelper下的配置。

spring:
  datasource:
    db1:
      driver-class-name: com.mysql.cj.jdbc.Driver
      jdbc-url: jdbc:mysql://localhost:3306/studb?characterEncoding=UTF-8&useUnicode=true
      username: root
      password: root
    db2:
      driver-class-name: oracle.jdbc.driver.OracleDriver
      jdbc-url: jdbc:oracle:thin:@//localhost:1521/XE
      username: root
      password: root
#  分页配置
  pagehelper:
    db1:
      dialect: mysql
      offsetAsPageNum: true
      rowBoundsWithCount: true
      reasonable: true
      supportMethodsArguments: true
      params: count=countSql;pageNum=pageNum;pageSize=pageSize;
    db2:
      dialect: oracle
      offsetAsPageNum: true
      rowBoundsWithCount: true
      reasonable: true
      supportMethodsArguments: true
      params: count=countSql;pageNum=pageNum;pageSize=pageSize;

3.1.3 yml中分页配置设置到对应Bean

        这里使用@ConfigurationProperties注解将yml配置文件中指定前缀的数据自动填充到Bean。

(1)db1数据源的分页属性Bean

@Data
@Component
@ConfigurationProperties(prefix = "spring.pagehelper.db1")
public class PrimaryMybatisProperties {
    private String dialect;
    private String offsetAsPageNum;
    private String rowBoundsWithCount;
    private String reasonable;
    private String supportMethodsArguments;
    private String params;
}

(2)db2数据源的分页属性Bean

@Data
@Component
@ConfigurationProperties(prefix = "spring.pagehelper.db2")
public class SecondMybatisProperties {
    private String dialect;
    private String offsetAsPageNum;
    private String rowBoundsWithCount;
    private String reasonable;
    private String supportMethodsArguments;
    private String params;
}

3.1.4 数据源配置

(1)db1的数据源配置PrimaryDataSourceConfig.java

注意:多数据源情况下这里使用@Primary注解指定默认使用的是db1。

@Configuration
@MapperScan(basePackages = "com.wen.mapper1", sqlSessionFactoryRef = "sqlSessionFactory1")
public class PrimaryDataSourceConfig {
    @Resource
    private PrimaryMybatisProperties primaryMybatisProperties;

    @Bean(name = "dataSource1")
    @Primary
    @ConfigurationProperties(prefix = "spring.datasource.db1")
    public DataSource dataSource1(){
        return DataSourceBuilder.create().build();
    }

    @Bean(name = "sqlSessionFactory1")
    @Primary
    public SqlSessionFactory sqlSessionFactory1(@Qualifier("dataSource1") DataSource dataSource1) throws Exception{
        SqlSessionFactoryBean sessionFactoryBean = new SqlSessionFactoryBean();
        sessionFactoryBean.setDataSource(dataSource1);
        String locationPattern = "classpath*:mapper1/**/*.xml";
        PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
        sessionFactoryBean.setMapperLocations(resolver.getResources(locationPattern));
        // mybatis
        org.apache.ibatis.session.Configuration configuration = new org.apache.ibatis.session.Configuration();
        configuration.setMapUnderscoreToCamelCase(true);
        configuration.setLogImpl(StdOutImpl.class);
        sessionFactoryBean.setConfiguration(configuration);
        // 分页
        Interceptor interceptor = new PageInterceptor();
        Properties properties = new Properties();
        properties.setProperty("helperDialect", primaryMybatisProperties.getDialect());
        properties.setProperty("offsetAsPageNum", primaryMybatisProperties.getOffsetAsPageNum());
        properties.setProperty("rowBoundsWithCount", primaryMybatisProperties.getRowBoundsWithCount());
        properties.setProperty("reasonable", primaryMybatisProperties.getReasonable());
        properties.setProperty("supportMethodsArguments",primaryMybatisProperties.getSupportMethodsArguments());
        properties.setProperty("params",primaryMybatisProperties.getParams());
        interceptor.setProperties(properties);
        sessionFactoryBean.setPlugins(interceptor);
        return sessionFactoryBean.getObject();
    }
    @Bean(name = "sqlSessionTemplate1")
    @Primary
    public SqlSessionTemplate sqlSessionTemplate1(@Qualifier("sqlSessionFactory1") SqlSessionFactory sqlSessionFactory1) {
        return new SqlSessionTemplate(sqlSessionFactory1);
    }

    @Bean(name = "dataSourceTransactionManager1")
    @Primary
    public DataSourceTransactionManager dataSourceTransactionManager1(@Qualifier("dataSource1") DataSource dataSource1){
        return new DataSourceTransactionManager(dataSource1);

    }
}

(2)db2的数据源配置SecondDataSourceConfig.java

@Configuration
@MapperScan(basePackages = "com.wen.mapper2",sqlSessionFactoryRef = "sqlSessionFactory2")
public class SecondDataSourceConfig {
    @Resource
    private SecondMybatisProperties secondMybatisProperties;

    @Bean(name = "dataSource2")
    @Primary
    @ConfigurationProperties(prefix = "spring.datasource.db2")
    public DataSource dataSource2(){
        return DataSourceBuilder.create().build();
    }

    @Bean(name = "sqlSessionFactory2")
    @Primary
    public SqlSessionFactory sqlSessionFactory1(@Qualifier("dataSource2") DataSource dataSource2) throws Exception{
        SqlSessionFactoryBean sessionFactoryBean = new SqlSessionFactoryBean();
        sessionFactoryBean.setDataSource(dataSource2);
        String locationPattern = "classpath*:mapper2/**/*.xml";
        PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
        sessionFactoryBean.setMapperLocations(resolver.getResources(locationPattern));
        // mybatis下划线转驼峰
        org.apache.ibatis.session.Configuration configuration = new org.apache.ibatis.session.Configuration();
        configuration.setMapUnderscoreToCamelCase(true);
        configuration.setLogImpl(StdOutImpl.class);
        sessionFactoryBean.setConfiguration(configuration);
        // 分页配置
        Interceptor interceptor = new PageInterceptor();
        Properties properties = new Properties();
        properties.setProperty("helperDialect", secondMybatisProperties.getDialect());
        properties.setProperty("offsetAsPageNum", secondMybatisProperties.getOffsetAsPageNum());
        properties.setProperty("rowBoundsWithCount", secondMybatisProperties.getRowBoundsWithCount());
        properties.setProperty("reasonable", secondMybatisProperties.getReasonable());
        properties.setProperty("supportMethodsArguments",secondMybatisProperties.getSupportMethodsArguments());
        properties.setProperty("params",secondMybatisProperties.getParams());
        interceptor.setProperties(properties);
        sessionFactoryBean.setPlugins(interceptor);
        return sessionFactoryBean.getObject();
    }
    @Bean(name = "sqlSessionTemplate2")
    @Primary
    public SqlSessionTemplate sqlSessionTemplate1(@Qualifier("sqlSessionFactory2") SqlSessionFactory sqlSessionFactory2) {
        return new SqlSessionTemplate(sqlSessionFactory2);
    }

    @Bean(name = "dataSourceTransactionManager2")
    @Primary
    public DataSourceTransactionManager dataSourceTransactionManager1(@Qualifier("dataSource2") DataSource dataSource2){
        return new DataSourceTransactionManager(dataSource2);

    }
}

注意:如果项目中有使用@Transactional事务注解,必须分别配置数据源的事务管理,以上代码中已经配置。

3.1.5 启动类排除相关自动配置

        启动类排除数据源(DataSourceAutoConfiguration.class)、Mybatis(MybatisAutoConfiguration.class)、分页(PageHelperAutoConfiguration.class)的自动配置。

@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class, MybatisAutoConfiguration.class, PageHelperAutoConfiguration.class})
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

}

3.2 示例代码

3.2.1 po

src/main/java/com/wen/po

@Data
public class Student {
    private Integer id;
    private String name;
    private Integer age;
    private String gender;
    private String address;
    private Date birth;
}
@Data
public class User {
    private String id;
    private String userName;
}

3.2.2 controller层

src/main/java/com/wen/controller

@RestController
@RequestMapping("/student")
public class StudentController {
    @Resource
    private StudentServiceI studentService;

    @GetMapping
    public PageInfo<Student> queryByPage(int pageNum, int pageSize, Student student){
        return studentService.queryByPage(pageNum,pageSize,student);
    }
}
@RestController
@RequestMapping("/user")
public class UserController {
    @Resource
    private UserServiceI userService;

    @GetMapping
    public PageInfo<User> queryByPage(int pageNum, int pageSize, User user){
        return userService.queryByPage(pageNum,pageSize,user);
    }
}

3.2.3 service层

src/main/java/com/wen/service

public interface StudentServiceI {
    PageInfo<Student> queryByPage(int pageNum, int pageSize, Student student);

}
@Service
public class StudentServiceImpl implements StudentServiceI {
    @Resource
    private StudentMapper studentMapper;
    @Override
    public PageInfo<Student> queryByPage(int pageNum, int pageSize, Student student) {
        if (pageNum <= 0) {
            pageNum = 1;
        }
        if (pageSize <= 0) {
            pageSize = 10;
        }
        if(ObjectUtil.isEmpty(student)){
            student = new Student();
        }
        PageMethod.startPage(pageNum,pageSize);
        List<Student> students = studentMapper.selectByPage(student);
        PageInfo<Student> pageInfo = new PageInfo<>(students);
        return pageInfo;
    }
}
public interface UserServiceI {
    PageInfo<User> queryByPage(int pageNum, int pageSize, User user);
}
@Service
public class UserServiceImpl implements UserServiceI {
    @Resource
    private UserMapper userMapper;
    @Override
    public PageInfo<User> queryByPage(int pageNum, int pageSize, User user) {
        if (pageNum <= 0) {
            pageNum = 1;
        }
        if (pageSize <= 0) {
            pageSize = 10;
        }
        if(ObjectUtil.isEmpty(user)){
            user = new User();
        }
        PageMethod.startPage(pageNum,pageSize);
        List<User> users = userMapper.selectByPage(user);
        PageInfo<User> pageInfo = new PageInfo<>(users);
        return pageInfo;
    }
}

3.2.4 mapper层

        注意不同数据源对应的mapper,数据源配置类中@MapperScan对应的属性basePackages = "com.wen.mapper2"指定数据源对应的mapper。

(1)db1数据源对应的mapper层

src/main/java/com/wen/mapper1/StudentMapper.java

@Mapper
public interface StudentMapper {
    List<Student> selectByPage(@Param("student") Student student);
}

src/main/resources/mapper1/StudentMapper.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.wen.mapper1.StudentMapper">
    <sql id="student">
        id,name,age,gender,address,birth
    </sql>
    <select id="selectByPage" resultType="com.wen.po.Student">
        select
        <include refid="student"/>
        from student
        <where>
            <if test="student.id!=null">
                and id = #{student.id}
            </if>
            <if test="student.name!=null and student.name!=''">
                <bind name="stuName" value="'%' + student.name + '%'"/>
                and name like #{stuName}
            </if>
        </where>
    </select>
</mapper>

(2)db2数据源对应的mapper层

src/main/java/com/wen/mapper2/UserMapper.java

@Mapper
public interface UserMapper {
    List<User> selectByPage(@Param("user") User user);
}

src/main/resources/mapper2/UserMapper.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.wen.mapper2.UserMapper">
    <sql id="user">
        id,user_name
    </sql>
    <select id="selectByPage" resultType="com.wen.po.User">
        select
        <include refid="user"/>
        from sys_user
        <where>
            <if test="user.id!=null">
                and id = #{student.id}
            </if>
            <if test="user.userName!=null and user.userName!=''">
                <bind name="userName" value="'%' + user.userName + '%'"/>
                and user_name like #{userName}
            </if>
        </where>
    </select>
</mapper>

3.3 测试

        使用Postman进行测试,如下:

(1)使用db1数据源

(2)使用db2数据源

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1103824.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Linux内核8. 进程地址空间

进程地址空间也就是每个进程所使用的内存&#xff0c;内核对进程地址空间的管理&#xff0c;也就是对用户态程序的内存管理。 主要内容&#xff1a; 地址空间(mm_struct)虚拟内存区域(VMA)地址空间和页表 1. 地址空间(mm_struct) 地址空间就是每个进程所能访问的内存地址范围…

React高级特性之RenderProps

一、概念 renderProps是另外一个能实现类似于HOC这种多个组件抽离公共组件逻辑的方式。 二、例子 import React from react import PropTypes from prop-typesclass Mouse extends React.Component {constructor(props) {super(props)this.state { x: 0, y: 0 }}handleMouse…

日志技术快速入门

1、创建Maven项目 这里不再说如何创建Maven项目 2、导入相关依赖 <dependency><groupId>ch.qos.logback</groupId><artifactId>logback-classic</artifactId><version>1.2.12</version></dependency>3、创建配置文件 在re…

Spring源码解析——事务增强器

正文 上一篇文章我们讲解了事务的Advisor是如何注册进Spring容器的&#xff0c;也讲解了Spring是如何将有配置事务的类配置上事务的&#xff0c;实际上也就是用了AOP那一套&#xff0c;也讲解了Advisor&#xff0c;pointcut验证流程&#xff0c;至此&#xff0c;事务的初始化工…

强化学习------Policy Gradient算法

目录 简介PG算法原理效果&#xff1a;参考 简介 之前的QLearning DQN Sarsa都是通过计算动作得分来决策的&#xff0c;我们是在确定了价值函数的基础上采用某种策略&#xff0c;即Value-Based&#xff0c;通过先算出价值函数&#xff0c;再去做决策。而Policy Gradient算法是一…

云计算:shell脚本

shell脚本&#xff0c;会极大减少重复性工作&#xff0c;缩短很大时间。 脚本每个人都可以不一样&#xff0c;只要实现就可以。 注意&#xff1a;要多思考&#xff0c;把思路锻炼好。以后就可以写各种程序。 shell语言 学完shell之后&#xff0c;对Linux理解更深刻&#xff…

在调试器下看微信[如何耗电]

在今天这样干什么都离不开手机的时代里&#xff0c;手机的待机时间太重要了。特别是对于我这个不喜欢带充电宝出门的人来说&#xff0c;一旦看到手机电量低于20%&#xff0c;立刻就精神紧张了&#xff0c;因为一切信息都在手机里&#xff0c;如果手机没电&#xff0c;那么就失联…

[SQL | MyBatis] MyBatis 简介

目录 一、MyBatis 简介 1、MyBatis 简介 2、工作流程 二、入门案例 1、准备工作 2、示例 三、Mapper 代理开发 1、问题简介 2、工作流程 3、注意事项 4、测试 四、核心配置文件 mybatis-config.xml 1、environment 2、typeAilases 五、基于 xml 的查询操作 1、…

通过stream对list集合中对象的多个字段进行去重

记录下通过stream流对list集合中对象的多个字段进行去重&#xff01; 举个栗子&#xff0c;对象book&#xff0c;我们要通过姓名和价格这两个字段的值进行去重&#xff0c;该这么做呢&#xff1f; distinct&#xff08;&#xff09;返回由该流的不同元素组成的流。distinct&am…

第五届芜湖机器人展,正运动助力智能装备“更快更准”更智能!

■展会名称&#xff1a; 第十一届中国(芜湖)科普产品博览交易会-第五届机器人展 ■展会日期 2023年10月21日-23日 ■展馆地点 中国ㆍ芜湖宜居国际博览中心B馆 ■展位号 B029 正运动技术&#xff0c;作为国内领先的运动控制企业&#xff0c;将于2023年10月21日参加芜湖机…

查看双翌视觉软件版本号

查看双翌视觉软件版本号 MasterAlign视觉对位软件 MasterAlign视觉对位软件的版本号在软件界面的右下角&#xff0c;如下图所示&#xff1a; 进入界面查看右下角编号尾号为O的代表旧协议版本 而编号尾号为N的则为新协议版本。 WiseAlign视觉对位软件 打开WiseAlign视觉对位软…

靶机 Chill_Hack

Chill_Hack 信息搜集 存活检测 arp-scan -l 详细扫描 扫描结果 显示允许 ftp 匿名链接 FTP 匿名登录 匿名登陆 ftp 下载文件并查看 anonymous10.4.7.139下载命令 get note.txt查看文件 译 Anurodh告诉我&#xff0c;在命令 Apaar 中有一些字符串过滤后台扫描 扫描结果…

【算法挨揍日记】day16——525. 连续数组、1314. 矩阵区域和

525. 连续数组 525. 连续数组 题目描述&#xff1a; 给定一个二进制数组 nums , 找到含有相同数量的 0 和 1 的最长连续子数组&#xff0c;并返回该子数组的长度。 解题思路&#xff1a; 本题的元素只有0和1&#xff0c;根据题目意思&#xff0c;我们可以把题目看成找一段最…

Educational Codeforces Round 156 (Rated for Div. 2)

C. Decreasing String 分析&#xff1a;暴力做法是很容易想到的&#xff0c;但时间复杂度为O(n2) 这是我打cf以来看到的最好的题解。 #include<cstdio> #include<set> #include<list> #include<queue> #include<math.h> #include<stdlib.h&g…

5.DApp-前端网页怎么连接MetaMask

题记 在前端网页连接metamask&#xff0c;以下是全部操作流程和代码。 编写index.html文件 index.html文件如下&#xff1a; <!DOCTYPE html> <html> <head> <title>My DApp</title> <!--导入用于检测Metamask提供者的JavaScript库--> &l…

嵌入式开发学习之STM32F407定时器中断配置(四)

嵌入式开发学习之STM32F407定时器中断配置&#xff08;四&#xff09; 此次实现目的开发涉及工具一、TIM参数配置和中断配置二、TIM的中断服务函数 此次实现目的 1.配置一个TIM进行计时&#xff0c;让一颗LED以点亮500ms&#xff0c;熄灭500ms的方式闪烁&#xff1b; 有工程实…

【JVM】对象内存布局

对象内存布局 文章目录 对象内存布局1. 对象的内存布局2. 对象标记(Mark Word)3. 类元信息(类型指针)4. 实例数据和对象填充 1. 对象的内存布局 在Hotspot虚拟机里&#xff0c;对象在堆内存中的存储布局可以划分为三个部分&#xff1a;对象头(Header)、实例数据(Instance Data…

华为云云耀云服务器L实例评测|使用Benchmark工具对云耀云服务器Elasticsearch的性能测试

目录 引言 1 在centos上安装Elasticsearch 1.1在服务器上安装 Docker 1.2 查找Elasticsearch镜像 1.3 安装并运行 Elasticsearch 容器 2 性能测试 Elasticsearch 2.1 安装 Apache Benchmark 工具 2.2 使用Benchmark进行性能测试 3 性能分析 3.1 性能测试结果 3.2 性能…

堆/二叉堆详解[C/C++]

前言 堆是计算机科学中-类特殊的数据结构的统称。实现有很多,例如:大顶堆,小顶堆&#xff0c;斐波那契堆&#xff0c;左偏堆&#xff0c;斜堆等等。从子结点个数上可以分为二汊堆&#xff0c;N叉堆等等。本文将介绍的是二叉堆。 二叉堆的概念 1、引例 我们小时候&#xff0c;基…

网络安全常见问题隐患及其应对措施

随着数字化时代的到来&#xff0c;网络安全已经成为组织和个人面临的严重挑战之一。网络攻击日益普及&#xff0c;黑客和不法分子不断寻找机会侵入系统、窃取敏感信息、破坏服务和网络基础设施。在这种情况下&#xff0c;了解网络安全的常见问题隐患以及如何应对它们至关重要。…