mybatis-plus接入多数据源

需求

 我所在项目的代码要接入当前数据库所在的服务器下的另外一个数据库的一张表,所以我这个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:事务我没测是不是可以同时处理啊

小白一枚,大神绕行

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值