记得面试时候,有面试官会问道,你们多数据源是怎么实现的呀。…….,一阵蒙蔽中,然后说道我们之前项目中,没有用到多数据源。
所幸,目前做得项目中有一个业务逻辑中,用到多个数据库数据情况,多数据源华丽上线。
因为我们项目是springboot+mybatis plus,有些人一看,mybatis还知道对吧,mybatis plus是什么鬼,其实字面意思可以理解,就是对mybatis进行一些功能改造,一些封装升级,然后用起来特别方便。
核心功能的升级主要是以下三点:
支持通用的 CRUD、代码生成器与条件构造器。
通用 CRUD:定义好 Mapper 接口后,只需要继承 BaseMapper<T> 接口即可获得通用的增删改查功能,无需编写任何接口方法与配置文件
条件构造器:通过 EntityWrapper<T> (实体包装类),可以用于拼接 SQL 语句,并且支持排序、分组查询等复杂的 SQL
代码生成器:支持一系列的策略配置与全局配置,比 MyBatis 的代码生成更好用
思路:
1、yml中配置多个数据源信息
2、通过AOP切换不同数据源
3、配合mybatis plus使用
1、yml配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
spring:
aop:
proxy-target-class: true
auto: true
datasource:
druid:
db1:
url: jdbc:mysql://localhost:3306/eboot
username: root
password: root
driver-class-name: com.mysql.jdbc.Driver
initialSize: 5
minIdle: 5
maxActive: 20
db2:
url: jdbc:oracle:thin:@192.168.136.222:ORCL
username: sa
password: sa123456
driver-class-name: oracle.jdbc.OracleDriver
initialSize: 5
minIdle: 5
maxActive: 20
|
2、启动多个数据源
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
|
@EnableTransactionManagement //开启事务
@Configuration //spring中常用到注解,与xml配置相对立。是两种加载bean方式
@MapperScan ( "com.df.openapi.**.mapper.db*" ) // 扫描mapperdao的地址
public class MybatisPlusConfig {
@Bean
public PaginationInterceptor paginationInterceptor() {
PaginationInterceptor paginationInterceptor = new PaginationInterceptor();
// paginationInterceptor.setLocalPage(true); // 由于版本问题,有些类可能招不到这个方法,需要升级jar包
return paginationInterceptor;
}
@Bean (name = "db1" )
@ConfigurationProperties (prefix = "spring.datasource.druid.db1" )
public DataSource db1() {
return DruidDataSourceBuilder.create().build();
}
@Bean (name = "db2" )
@ConfigurationProperties (prefix = "spring.datasource.druid.db2" )
public DataSource db2() {
return DruidDataSourceBuilder.create().build();
}
/**
* 动态数据源配置
*
* @return
*/
@Bean
@Primary
public DataSource multipleDataSource( @Qualifier ( "db1" ) DataSource db1,
@Qualifier ( "db2" ) DataSource db2) {
DynamicDataSource dynamicDataSource = new DynamicDataSource();
Map<Object, Object> targetDataSources = new HashMap<>();
targetDataSources.put(DBTypeEnum.db1.getValue(), db1);
targetDataSources.put(DBTypeEnum.db2.getValue(), db2);
dynamicDataSource.setTargetDataSources(targetDataSources);
dynamicDataSource.setDefaultTargetDataSource(db2); // 程序默认数据源,这个要根据程序调用数据源频次,经常把常调用的数据源作为默认
return dynamicDataSource;
}
@Bean ( "sqlSessionFactory" )
public SqlSessionFactory sqlSessionFactory() throws Exception {
MybatisSqlSessionFactoryBean sqlSessionFactory = new MybatisSqlSessionFactoryBean();
sqlSessionFactory.setDataSource(multipleDataSource(db1(), db2()));
MybatisConfiguration configuration = new MybatisConfiguration();
configuration.setJdbcTypeForNull(JdbcType.NULL);
configuration.setMapUnderscoreToCamelCase( true );
configuration.setCacheEnabled( false );
sqlSessionFactory.setConfiguration(configuration);
//PerformanceInterceptor(),OptimisticLockerInterceptor()
//添加分页功能
sqlSessionFactory.setPlugins( new Interceptor[]{
paginationInterceptor()
});
// sqlSessionFactory.setGlobalConfig(globalConfiguration()); //注释掉全局配置,因为在xml中读取就是全局配置
return sqlSessionFactory.getObject();
}
/* @Bean
public GlobalConfiguration globalConfiguration() {
GlobalConfiguration conf = new GlobalConfiguration(new LogicSqlInjector());
conf.setLogicDeleteValue("-1");
conf.setLogicNotDeleteValue("1");
conf.setIdType(0);
conf.setMetaObjectHandler(new MyMetaObjectHandler());
conf.setDbColumnUnderline(true);
conf.setRefresh(true);
return conf;
}*/
}
|
3、DBType枚举类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
package com.df.openapi.config.db;
public enum DBTypeEnum {
db1( "db1" ), db2( "db2" );
private String value;
DBTypeEnum(String value) {
this .value = value;
}
public String getValue() {
return value;
}
}
|
4、动态数据源决策
1
2
3
4
5
6
7
8
9
10
11
12
13
|
package com.df.openapi.config.db;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
public class DynamicDataSource extends AbstractRoutingDataSource {
private static final Logger LOGGER = LoggerFactory.getLogger(DynamicDataSource. class );
@Override
protected Object determineCurrentLookupKey() {
String datasource = DataSourceContextHolder.getDbType();
LOGGER.debug( "使用数据源 {}" , datasource);
return datasource;
}
}
|
5、设置、获取数据源
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
public class DataSourceContextHolder {
private static final Logger LOGGER = LoggerFactory.getLogger(DataSourceContextHolder. class );
private static final ThreadLocal contextHolder = new ThreadLocal<>(); //实际上就是开启多个线程,每个线程进行初始化一个数据源
/**
* 设置数据源
* @param dbTypeEnum
*/
public static void setDbType(DBTypeEnum dbTypeEnum) {
contextHolder.set(dbTypeEnum.getValue());
}
/**
* 取得当前数据源
* @return
*/
public static String getDbType() {
return (String) contextHolder.get();
}
/**
* 清除上下文数据
*/
public static void clearDbType() {
contextHolder.remove();
}
}
|
6、AOP实现的数据源切换
@Order设置的足够小是为了让他先执行
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
/**
* aop的实现的数据源切换<br> * aop切点,实现mapper类找寻,找到所属大本营以后,如db1Aspect(),则会调用<br> * db1()前面之前的操作,进行数据源的切换。
*/
@Component
@Order (value = - 100 )
@Slf4j
@Aspect
public class DataSourceAspect {
@Pointcut ( "execution(* com.zwyl.bazhong.dao.mapper.db1..*.*(..))" )
private void db1Aspect() {
}
@Pointcut ( "execution(* com.zwyl.bazhong.dao.mapper.db2..*.*(..))" )
private void db2Aspect() {
}
@Before ( "db1Aspect()" )
public void db1() {
log.info( "切换到db1 数据源..." );
DataSourceContextHolder.setDbType(DBTypeEnum.db1);
}
@Before ( "db2Aspect()" )
public void db2() {
log.info( "切换到db2 数据源..." );
DataSourceContextHolder.setDbType(DBTypeEnum.db2);
}
}
|
7、mapper层结构
8、写一个service测试一下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
@Service
public class DictServiceImpl implements IDictService {
@Resource
private PtDictMapper ptDictMapper; //来自db1
@Resource
private SysDictMapper sysDictMapper; // 来自db2
@Override
public void getById(String id) {
PtDict dict = ptDictMapper.selectById( "2bf6257fc8fe483c84c1ad7e89d632f6" );
SysDict sysDict = sysDictMapper.getById( "49" );
System.out.println( "123" );
}
}
|
9、测试结果
总结: 其实整个过程可以理解成,配置多数据源 xml中 ——-> 然后通过加载多数源到spring工厂中——–>然后创建多线程,每个数据源对应一个数据源———>然后实际调用时候,会先通过aop匹配到某一具体数据源————->然后实例化当前数据源
到此这篇关于Mybatis plus 配置多数据源的实现示例的文章就介绍到这了,更多相关Mybatis plus 多数据源内容请搜索快网idc以前的文章或继续浏览下面的相关文章希望大家以后多多支持快网idc!
原文链接:https://www.cnblogs.com/CryOnMyShoulder/p/12218876.html
相关文章
- 个人服务器网站搭建:如何选择适合自己的建站程序或框架? 2025-06-10
- 64M VPS建站:能否支持高流量网站运行? 2025-06-10
- 64M VPS建站:怎样选择合适的域名和SSL证书? 2025-06-10
- 64M VPS建站:怎样优化以提高网站加载速度? 2025-06-10
- 64M VPS建站:是否适合初学者操作和管理? 2025-06-10
- 2025-07-10 怎样使用阿里云的安全工具进行服务器漏洞扫描和修复?
- 2025-07-10 怎样使用命令行工具优化Linux云服务器的Ping性能?
- 2025-07-10 怎样使用Xshell连接华为云服务器,实现高效远程管理?
- 2025-07-10 怎样利用云服务器D盘搭建稳定、高效的网站托管环境?
- 2025-07-10 怎样使用阿里云的安全组功能来增强服务器防火墙的安全性?
快网idc优惠网
QQ交流群
-
2025-05-29 64
-
2025-06-04 92
-
2025-05-25 41
-
2025-05-25 31
-
2025-05-27 46