需求
我所在项目的代码要接入当前数据库所在的服务器下的另外一个数据库的一张表,所以我这个springboot项目要接入同一个服务器下的两个不同的数据库
推荐博客:
官方文档:多数据源 | MyBatis-Plus (baomidou.com)
Mybatis | Mybatis-plus配置多数据源,连接多数据库_Cz范特西的博客-CSDN博客_mybatis-plus配置多数据源
MyBatisPlus--多数据源_杼蛘的博客-CSDN博客_mybatisplus多数据源
接入过程
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>dynamic-datasource-spring-boot-starter</artifactId>
<version>3.5.1</version>
</dependency>
附注:
我的操作相当于在一个service里,先从从数据库的一张表里查出数据,然后再把数据进行处理插入到主数据库的一张表里,因为项目里业务是定时任务,所以我直接在定时任务里进行两个数据源的操作
主数据库JdyInfoMapper
package cn.mn.ac.eff.mapper;
import cn.mn.ac.core.mp.base.BaseMapper;
import cn.mn.ac.eff.entity.JdyInfo;
public interface JdyMapper extends BaseMapper<JdyInfo> {
}
主数据库JdyInfoService
package cn.mn.ac.eff.service;
import cn.mn.ac.core.mp.base.BaseServiceImpl;
import cn.mn.ac.eff.entity.JdyInfo;
import cn.mn.ac.eff.mapper.JdyMapper;
import org.springframework.stereotype.Service;
@Service
public class JdyInfoService extends BaseServiceImpl<JdyMapper, JdyInfo> {
}
主数据库JdyInfo.class
package cn.mn.ac.eff.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.util.Date;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@TableName("jdy_info")
public class JdyInfo implements Serializable {
@TableId(value = "id", type = IdType.AUTO)
private String id;
private String dataId;
private String formName;
private String number;
private String requireNo;
private String userName;
private String secondaryDept;
private String deptName;
private String requireType;
private String reqAcceptorEst;
private String reqAcceptorNumber;
private String reqAcceptorName;
private String reqAcceptorDept;
private String chargeType;
private double requireBudget;
private String isNeedOuter;
private String innerDays;
private String dueItem;
private double dueStartMoney;
private double dueEndMoney;
private double totalMoney;
private String formula;
private double remainMoney;
private String conclusion;
private String requireWay;
private Integer flowStatus;
private String flowStatusName;
private Date createTime;
private Date updateTime;
private String creator;
private String updater;
}
IterpJdyInfo.Mapper=====>从数据库一张表的mapper
package cn.mn.ac.eff.mapper;
import cn.mn.ac.core.mp.base.BaseMapper;
import cn.mn.ac.eff.entity.IterpJdyInfo;
public interface IterpJdyMapper extends BaseMapper<IterpJdyInfo> {
}
从数据库IterpJdyInfoService
package cn.mn.ac.eff.service;
import cn.mn.ac.core.mp.base.BaseServiceImpl;
import cn.mn.ac.eff.entity.IterpJdyInfo;
import cn.mn.ac.eff.mapper.IterpJdyMapper;
import com.baomidou.dynamic.datasource.annotation.DS;
import org.springframework.stereotype.Service;
@Service
@DS("second")
public class IterpJdyService extends BaseServiceImpl<IterpJdyMapper, IterpJdyInfo> {
}
从数据库IterpJdyInfo.clas
package cn.mn.ac.eff.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@TableName("record_list")
public class IterpJdyInfo implements Serializable {
private static final long serialVersionUID = -4788457616802723223L;
@TableId(value = "id", type = IdType.AUTO)
private Long id;
private Integer source;
private String event;
private String recordId;
private Long createTime;
private String content;
}
Job======>定时任务【直接对两个数据源进行操作,这里不能直接使用两个数据源的service】
package cn.mn.ac.eff.schedule.jobs;
import cn.mn.ac.core.tool.jackson.JsonUtil;
import cn.mn.ac.core.tool.utils.*;
import cn.mn.ac.eff.constant.CommonAttributeConstant;
import cn.mn.ac.eff.constant.CommonSql;
import cn.mn.ac.eff.entity.IterpJdyInfo;
import cn.mn.ac.eff.entity.JdyInfo;
import cn.mn.ac.eff.mapper.IterpJdyMapper;
import cn.mn.ac.eff.mapper.JdyMapper;
import cn.mn.ac.eff.model.JdyReqData;
import cn.mn.ac.eff.schedule.TaskJob;
import com.baomidou.dynamic.datasource.toolkit.DynamicDataSourceContextHolder;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.fasterxml.jackson.databind.JsonNode;
import lombok.extern.slf4j.Slf4j;
import org.quartz.JobDataMap;
import org.quartz.JobExecutionException;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
/**
* 从iterp系统同步简道云数据job
*/
@Slf4j
public class SyncIterpJdyJob extends TaskJob {
private final IterpJdyMapper iterpJdyMapper = SpringUtil.getBean(IterpJdyMapper.class);
private final JdyMapper jdyMapper = SpringUtil.getBean(JdyMapper.class);
@Override
protected void runJob(JobDataMap dataMap, List<String> errors) throws JobExecutionException {
try {
log.info("sync iterp jdy job start.");
DynamicDataSourceContextHolder.push("second"); //操作从数据库
String iterpJdySql = CommonSql.iterp_jdy_sql();
List<IterpJdyInfo> iterpJdyInfos = iterpJdyMapper.selectList(Wrappers.lambdaQuery(IterpJdyInfo.class)
.inSql(IterpJdyInfo::getId, iterpJdySql)); //从数据库IterpJdyInfo表查询操作
DynamicDataSourceContextHolder.poll(); //关闭从数据库
DynamicDataSourceContextHolder.push("master"); //操作主数据库,进行主数据库中的JdyInfo表入库操作
List<JdyReqData> jdyReqDataList = iterpJdyInfos.stream().map(ele -> {
JsonNode resBodyRelate = JsonUtil.readTree(ele.getContent());
JdyReqData res = JsonUtil.parse(resBodyRelate.get("data").toString(), JdyReqData.class);
res.setDataId(ele.getRecordId());
return res;
}).collect(Collectors.toList());
List<JdyInfo> jdyInfos = jdyMapper.selectList(Wrappers.lambdaQuery(JdyInfo.class));
List<String> jdyRequireNos = jdyInfos.stream().map(JdyInfo::getRequireNo).filter(Objects::nonNull).distinct().collect(Collectors.toList());
List<String> removeRequireNos = jdyReqDataList.stream().filter(ele -> ele != null)
.filter(ele -> jdyRequireNos.contains(ele.getRequireNo()))
.filter(ele -> ele.getSecondaryDept() != null && StringUtil.isNotBlank(ele.getSecondaryDept().getName()))
.map(JdyReqData::getRequireNo).collect(Collectors.toList());
List<JdyInfo> jdyInfoList = jdyReqDataList.stream().filter(ele -> ele != null)
.filter(ele -> {
if (jdyRequireNos.contains(ele.getRequireNo()) && (ele.getSecondaryDept() == null || StringUtil.isBlank(ele.getSecondaryDept().getName())))
return false;
return true;
}).map(ele -> {
JdyInfo jdyInfo = BeanUtil.copy(ele, JdyInfo.class);
jdyInfo.setUserName(ele.getUserInfo() != null ? ele.getUserInfo().getName() : "");
jdyInfo.setCreator(ele.getCreator() != null ? ele.getCreator().getName() : "");
jdyInfo.setUpdater(ele.getUpdater() != null ? ele.getUpdater().getName() : "");
jdyInfo.setDeptName(ele.getDeptInfo() != null ? ele.getDeptInfo().getName() : "");
jdyInfo.setFlowStatus(ele.getFlowStatus() != null ? Integer.valueOf(ele.getFlowStatus()) : null);
if (ele.getFlowStatus() != null)
jdyInfo.setFlowStatusName(CommonAttributeConstant.FLOWSTATUSMAP.getOrDefault(Integer.valueOf(ele.getFlowStatus()), ""));
jdyInfo.setCreateTime(ele.getCreateTime());
jdyInfo.setUpdateTime(ele.getUpdateTime());
jdyInfo.setReqAcceptorDept(ele.getReqAcceptorDept() != null ? ele.getReqAcceptorDept().getName() : "");
jdyInfo.setReqAcceptorEst(ele.getReqAcceptorEst() != null ? ele.getReqAcceptorEst().getName() : "");
jdyInfo.setReqAcceptorName(ele.getReqAcceptorName() != null ? ele.getReqAcceptorName().getName() : "");
jdyInfo.setSecondaryDept(ele.getSecondaryDept() == null ? "" : ele.getSecondaryDept().getName());
return jdyInfo;
}).collect(Collectors.toList());
jdyMapper.delete(Wrappers.lambdaQuery(JdyInfo.class).in(JdyInfo::getRequireNo, removeRequireNos));
jdyMapper.insertBatch(jdyInfoList);
DynamicDataSourceContextHolder.poll(); //关闭操作主数据库
log.info("sync iterp jdy job end.");
} catch (Exception e) {
log.error(e.getMessage(), e);
errors.add(Exceptions.unwrap(e).getMessage());
}
}
}
配置中心使用的是nacos,关于多数据源的配置如下
spring:
redis:
host: 127.0.0.1
port: 6379
password:
database: 3
datasource:
dynamic:
primary: master
strict: false
datasource:
master: //主数据库
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/eff_sys?useSSL=false&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&transformedBitIsBoolean=true&tinyInt1isBit=false&allowMultiQueries=true&serverTimezone=GMT%2B8&allowPublicKeyRetrieval=true&rewriteBatchedStatements=true
username: root
password: root
druid:
max-active: 100
second: //从数据库
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/iterp?useSSL=false&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&transformedBitIsBoolean=true&tinyInt1isBit=false&allowMultiQueries=true&serverTimezone=GMT%2B8&allowPublicKeyRetrieval=true&rewriteBatchedStatements=true
username: root
password: root
druid:
max-active: 100
建议:
建议可以看一下我这篇文章推荐博客的第一个博客,讲得很详细
PS:事务我没测是不是可以同时处理啊