SpringBoot+MyBatis多数据源场景下mapper.xml跨库插入最佳实践咨询
SpringBoot+MyBatis多数据源场景跨库插入最佳实现方案
分两种场景选择适配方案:
场景1:两个数据库部署在同一个MySQL实例下(性能最高,优先选择)
前提条件
你配置的MyBatis数据源对应的数据库账号,同时拥有database1的查询权限和database2的写入权限,不需要额外配置多数据源。
实现代码
你原来的SQL缺少SELECT查询部分,修正后的mapper.xml写法如下:
<insert id="insertFromODS"> INSERT INTO database2.target_table (col1, col2, col3, ...) SELECT tb1.col1, tb2.col2, tb1.col3 FROM database1.table1 AS tb1 LEFT JOIN database1.table2 AS tb2 ON tb1.id = tb2.id <!-- 可补充WHERE条件过滤需要插入的数据 --> </insert>
优化建议
不要在XML硬编码数据库名,建议把库名放在配置文件中通过MyBatis参数注入,方便多环境切换:
- 配置文件添加配置:
custom: datasource: ods-db-name: database1 business-db-name: database2
- Mapper接口添加参数:
int insertFromODS(@Param("odsDbName") String odsDbName, @Param("businessDbName") String businessDbName);
- XML中注入变量:
<insert id="insertFromODS"> INSERT INTO ${businessDbName}.target_table (col1, col2, col3) SELECT tb1.col1, tb2.col2, tb1.col3 FROM ${odsDbName}.table1 AS tb1 LEFT JOIN ${odsDbName}.table2 AS tb2 ON tb1.id = tb2.id </insert>
这个方案所有操作都在数据库层面完成,没有应用层数据传输开销,性能最好。
场景2:两个数据库部署在不同实例下(跨实例场景)
这种场景单个数据库连接无法访问另一个实例的库,不能直接写带库名的SQL,需要走多数据源配置+应用层处理:
- 第一步:配置SpringBoot多数据源,分别绑定
database1和database2的连接信息,给两个库配置独立的SqlSessionFactory、Mapper扫描路径,比如database1的Mapper放在mapper/ods包下,database2的Mapper放在mapper/business包下 - 第二步:分两步操作:
- 调用
database1对应的Mapper,查询关联后的结果集,数据量大的话做分页查询 - 调用
database2对应的Mapper,批量插入拿到的结果集,和查询逻辑对应做分批插入避免OOM
- 调用
- 如果需要保证跨库操作的事务一致性,需要引入分布式事务方案。
内容的提问来源于stack exchange,提问作者BertramLAU
相关产品推荐
相关产品推荐

