多数据源程序开发
由于读写分离,主从实时备份等业务场景的需要,往往在开发数据库应用时,要配置多个数据源。本文结合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来解决这个问题。