多数据源程序开发

多数据源程序开发

由于读写分离,主从实时备份等业务场景的需要,往往在开发数据库应用时,要配置多个数据源。本文结合springboot,mybatis等应用框架,实现多数据源应用程序。

在build.grade 文件中添加springboot 依赖 ,

//动态数据源的依赖包
// https://mvnrepository.com/artifact/com.baomidou/dynamic-datasource-spring-boot-starter
implementation 'com.baomidou:dynamic-datasource-spring-boot-starter:3.5.2'

springboot 项目配置文件 application.yml

server:
  port: 8888


spring:
  web:
    resources:
      static-locations:
      - classpath:/static/
  mvc:
    static-path-pattern: /**

# 
  datasource:
    dynamic:
      primary: db-reomte   #默认数据库
      datasource:
        db-reomte:
          url: jdbc:mysql://10.8.0.5:3306/jmrc?useUnicode=true&characterEncoding=utf-8
          username: XXXX
          password: XXXX
          driver-class-name: com.mysql.cj.jdbc.Driver
        db-localhost:
          url: jdbc:mysql://localhost:3306/jmrc?useUnicode=true&characterEncoding=utf-8
          username: XXXX
          password: XXXX
          driver-class-name: com.mysql.cj.jdbc.Driver
      druid:
        initial-size: 5  #初始大小
        max-active: 20		#最大活跃
        min-idle: 5		#最小
        max-wait: 60000		#最长等待时间
        time-between-eviction-runs-millis: 60000  #俩次之间的间隔时间 毫秒
        min-evictable-idle-time-millis: 300000		#多长时间不访问就称最小
        validation-query: SELECT 1 FROM DUAL   #验证查询
        test-while-idle: true			#是否开启闲置测试
        test-on-borrow: false    #在这个上测试
        test-on-return: false   #开启返回测试
        filters: stat,wall,log4j  #配置过滤器
        stat:
          log-slow-sql: true
    

    
mybatis:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

其中,核心的内容是 datasource 部分, 默认数据设置 primary 是必定要的,dynamic 是动态数据源的依赖,如果前一骤没有引入这个依赖包的话,在配置这项时,就会提示出错。此外,数据源的名称可以自定义,如上而的db-localhost 和 db_remote 就是自定义的数据源名称。

使用注解来调用不同的数据库进行读写

package com.enixlin.double_database.service.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.baomidou.dynamic.datasource.annotation.DS;
import com.enixlin.double_database.mapper.SynamicMapper;
import com.enixlin.double_database.service.SynamicDBService;

@Service
public class SynamicServiceImpl implements SynamicDBService {

    private SynamicMapper synamicMapper;

    @Autowired
    public SynamicServiceImpl(SynamicMapper synamicMapper) {
        this.synamicMapper = synamicMapper;
    }

    @DS("db-remote")
    @Override
    public ArrayList<LinkedHashMap<String, String>> readFormRemoteDB() {
        // TODO Auto-generated method stub
        ArrayList<LinkedHashMap<String, String>> array = this.synamicMapper.readFormRemoteDB();
        return array;
    }

    @DS("db-localhost")
    @Override
    public int writeToLocalDB(ArrayList<LinkedHashMap<String, String>> array) {
        // TODO Auto-generated method stub
        if (array.size()!=0) {
            try {
                this.synamicMapper.writeToLocalDB(array);
            } catch (Exception e) {
                // TODO: handle exception
                System.out.println(e);
                e.printStackTrace();
            }
            
        }
      
       return array.size();
    }

}

注意上面的示例代码中,使用@DS("db-remote")注解,说明该方法是使用名称为"db-remote" 的数据源。(这里有一个坑,就是数据源的名称不能有下划线“_”,否则不会切换数据源,这个里要十分注意) 同理,也可以在类名层级加数据源注解,这样就可以实现这个类的所有操作都使用注解引用数据源。这样就比较灵活的实现动态数据源。但这样的使用方法也有不好的地方。例如有几十个类,或者上百个方法要添加不周的数据源,这样一个一个类,或者是一个一个方法来手工添加的话,效率是比较差的。一般可以使用AOP来解决这个问题。
DS()注解的使用注意点:

  1. 在controller、service, mapper 等层级都可以使用
  2. 建议在mapper层使用注解,这样在service层就可以内部调用不同的数据源,不用把业务逻辑放在controller里面

使用AOP来实现批量的动态数据源

posted @ 2022-11-10 17:36  江山老林  阅读(66)  评论(0)    收藏  举报