自学笔记:baomidou-dynamic-datasource(读写分离)

Dynamic-Datasource

dynamic-datasource-spring-boot-starter 是一个基于springboot的快速集成多数据源的启动器。

其支持 Jdk 1.7+, SpringBoot 1.5.x 和 2.x.x

作用:实现读写分离

特性

  1. 支持 数据源分组 ,适用于多种场景 纯粹多库 读写分离 一主多从 混合模式。
  2. 支持数据库敏感配置信息 加密 ENC()。
  3. 支持每个数据库独立初始化表结构schema和数据库database。
  4. 支持 自定义注解 ,需继承DS(3.2.0+)。
  5. 提供对Druid,Mybatis-Plus,P6sy,Jndi的快速集成。
  6. 简化Druid和HikariCp配置,提供 全局参数配置 。配置一次,全局通用。
  7. 提供 自定义数据源来源 方案。
  8. 提供项目启动后 动态增加移除数据源 方案。
  9. 提供Mybatis环境下的 纯读写分离 方案。
  10. 提供使用 spel动态参数 解析数据源方案。内置spel,session,header,支持自定义。
  11. 支持 多层数据源嵌套切换 。(ServiceA >>> ServiceB >>> ServiceC)。
  12. 提供对shiro,sharding-jdbc,quartz等第三方库集成的方案,注意事项和示例。
  13. 提供 基于seata的分布式事务方案。 附:不支持原生spring事务。

约定

  1. 本框架只做 切换数据源 这件核心的事情。
  2. 配置文件所有以下划线 _ 分割的数据源 首部 即为组的名称,相同组名称的数据源会放在一个组下。
  3. 切换数据源可以是组名,也可以是具体数据源名称。组名则切换时采用负载均衡算法切换。
  4. 默认的数据源名称为 master ,你可以通过 spring.datasource.dynamic.primary 修改。
  5. @DS注解可以注解在类或方法上。方法上的注解优先于类上注解。

快速入门

  1. 创建一个springboot工程,导入mysql、druid和Dynamic-Datasource的启动器。

        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
    
            <!--导入druid的启动器-->
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>druid-spring-boot-starter</artifactId>
                <version>1.1.18</version>
            </dependency>
    
            <!--导入dynamic-datasource的启动器-->
            <dependency>
                <groupId>com.baomidou</groupId>
                <artifactId>dynamic-datasource-spring-boot-starter</artifactId>
                <version>3.2.1</version>
            </dependency>
    
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
            </dependency>
        </dependencies>
    
  2. 配置文件,配置主库从库。需要最少两个mysql服务。

    spring:
      datasource:
        dynamic:
          primary: master #设置默认的数据源或者数据源组,默认值即为master
          strict: false #设置严格模式,默认false不启动. 启动后在未匹配到指定数据源时候会抛出异常,不启动则使用默认数据源.
          datasource:
            master:   #配置主库
              url: jdbc:mysql://8.131.88.207:3306/test?serverTimezone=Asia/Shanghai
              username: 用户名
              password: 密码
              driver-class-name: com.mysql.cj.jdbc.Driver
            slave_1:    #配置从库
              url: jdbc:mysql:///test01?serverTimezone=Asia/Shanghai
              username: 用户名
              password: 密码
              driver-class-name: com.mysql.cj.jdbc.Driver
    
  3. 在启动类@SpringBootApplication注解中,排除原生Druid的配置类。因为项目默认连接Druid的原生配置的mysql服务。

    @SpringBootApplication(exclude = DruidDataSourceAutoConfigure.class)
    public class BaomidouDynamicDatasourceApplication {
    	public static void main(String[] args) {
    		SpringApplication.run(BaomidouDynamicDatasourceApplication.class, args);
    	}
    }
    
  4. 我的主库或从库都有一个同一结构的表:student表,只有idname两个属性。编写对应的实体类Student.class。

    public class Student {
        private int id;
        private String name;
        //省略get/set/constructor/toString方法
    }
    
  5. 编写dao层、service层与controller层。
    dao层中,如果想要从主库查询,默认不需要添加注解;如果想从从库中查询,则添加注解@DS("slave_1")slave_1 是在配置中定义的从库名称。

    例如我,查询从从库,读写在主库

    dao实现:

    @Repository
    public class StudentDaoImpl implements StudentDao {
        @Autowired
        private JdbcTemplate jdbcTemplate;
    
        @Override
        @DS("slave_1")      //表示读取数据源为从库,若没有注解则默认为主库
        public List<Student> allStudent() {
            return jdbcTemplate.query("select * from student ", new RowMapper<Student>() {
                @Override
                public Student mapRow(ResultSet resultSet, int i) throws SQLException {
                    Student student=new Student(Integer.parseInt(resultSet.getString("id")),resultSet.getString("name"));
                    return student;
                }
            });
        }
    
        @Override
        public void addStudent(String name) {
            jdbcTemplate.execute("INSERT INTO student(NAME) VALUES(' "+name+" '); ");
        }
    }
    

    service实现:

    @Service
    public class StudentServiceImpl implements StudentService {
        @Autowired
        private StudentDao studentDao;
        
        @Override
        public List<Student> allStudent() {
            return studentDao.allStudent();
        }
        @Override
        public void addStudent(String name) {
            studentDao.addStudent(name);
        }
    }
    

    controller层:

    @RestController
    public class Test {
        @Autowired
        private StudentService studentService;
    
        @GetMapping("allStudent")
        public String allStudent(){
            return  studentService.allStudent().toString();
        }
    
        @GetMapping("addStudent")
        public String addStudent(){
            studentService.addStudent("思绪");
            return "添加成功";
        }
    }
    
  6. 测试:我的两个mysql服务并没有主从复制,所以数据并不同步。

    • 添加数据:默认在主库中添加。
      自学笔记:baomidou-dynamic-datasource(读写分离)

    • 查找数据:从从库查找。
      自学笔记:baomidou-dynamic-datasource(读写分离)


集成MybatisPlus

  1. 首先导入Mybatis的依赖

    <dependency>
        <groupId>com.baomidou</groupId>
        <artifactId>mybatis-plus-boot-starter</artifactId>
        <version>3.4.0</version>
    </dependency>
    
  2. 在启动类配置@MapperScan扫描Mapper层

    @MapperScan("com.sixu.dao")
    
  3. 编写一个mapper层,StudentMapper.class,继承BaseMapper <Studen> , 就可以直接使用MybatisPlus内置的mapper层方法了。

    public interface StudentMapper extends BaseMapper<Student> {
    }
    
  4. 在service层调用这个mapper的方法,并且在在方法上添加@DS 验证效果。

       //读取从库
       @DS("slave_1")
       public List<Student> slave(){
           return studentMapper.selectList(null);
       }
       
       //读取主库
       public List<Student> master(){
           return studentMapper.selectList(null);
       }
    
  5. controller层

        //整合mybatisplus,实现读写分离,读取从库
        @GetMapping("slave")
        public String slave(){
            return studentService.test().toString();
        }
    
        //整合mybatisplus,实现读写分离,读取主库
        @GetMapping("master")
        public String master(){
            return studentService.test().toString();
        }
    
  6. 测试结果:
    自学笔记:baomidou-dynamic-datasource(读写分离)


上一篇:Photoshop CC Working with Filters Photoshop CC滤镜教程 Pluralsight课程中文字幕


下一篇:「Certbot」- The manual plugin is not working @20210307