spring boot如何实现动态数据源

12 篇文章 0 订阅

1,首先动态数据源需要可配置,可以动态修改,可以不需要重启相关服务器程序,达到配置修改后即及时生效.

2,所以排除了修改注解这一种方式,因为以现在的认知,注解是与代码绑定,需要修改代码,并且重新编译发布.

3,第二种xml配置,集中式管理配置,减少与代码的耦合,虽然springboot + devtools(热部署)可提供这种使应用不用重启可xml生效的能力,但不太适合提供增加的免费云数据源/服务器/虚拟主机,如原来就有的张三丰A数据源,后面动态增加B云数据,就得有三丰A,B云数据源.,数据库连接:h t t p s: // www.sanfengyun.com/datasrc/orgdatasrcA?useUnicode=true&characterEncoding=utf-8&serverTimezone=BeiJing.

4,建议用关系型数据库存储动态数据源配置,可按需要增加所需数据源,然后再根据数据库配置动态切换不同数据源.

5,说到连接数据库,那当然需要一个静态数据库,用来获取数据库配置数据,然后根据静态数据库的数据库配置数据生成动态数据.

如下是数据库配置实体类

/**
 * <p>
 * 表名:[data_src],数据源表 实体类
 * </p>
 * @author 
 * @since 2020-10-24
 */
@Entity
@Table(name="data_src")
@JsonIgnoreProperties(value = { "hibernateLazyInitializer", "handler" })
@TableName("data_src")
@ApiModel(value="DataSrc对象", description="数据源表")
public class DataSrc extends Model<DataSrc> {

    @ApiModelProperty(value = "主键")
    @TableId(value = "id", type = IdType.ID_WORKER)
    @Id
    @Column(name="id")
    private Long id;

    @ApiModelProperty(value = "版本")
    @TableField("version")
    @Column(name="version")
    @com.baomidou.mybatisplus.annotation.Version
    @javax.persistence.Version
    private Integer version;

    @ApiModelProperty(value = "创建人")
    @TableField(value = "create_by", fill = FieldFill.INSERT)
    @Column(name="create_by")
    private Long createBy;

    @ApiModelProperty(value = "创建人名称")
    @TableField("create_by_name")
    @Column(name="create_by_name")
    private String createByName;

    @ApiModelProperty(value = "创建时间")
    @TableField(value = "create_time", fill = FieldFill.INSERT)
    @Column(name="create_time")
    private LocalDateTime createTime;

    @ApiModelProperty(value = "更新人")
    @TableField(value = "last_up_by", fill = FieldFill.INSERT_UPDATE)
    @Column(name="last_up_by")
    private Long lastUpBy;

    @ApiModelProperty(value = "更新人名称")
    @TableField("last_up_by_name")
    @Column(name="last_up_by_name")
    private String lastUpByName;

    @ApiModelProperty(value = "更新时间")
    @TableField(value = "last_up_time", fill = FieldFill.INSERT_UPDATE)
    @Column(name="last_up_time")
    private LocalDateTime lastUpTime;

    @ApiModelProperty(value = "是否删除(1/0)默认0")
    @TableField("is_del")
    @Column(name="is_del")
    @TableLogic
    private Integer isDel;

    @ApiModelProperty(value = "备注")
    @TableField("remark")
    @Column(name="remark")
    private String remark;

    @ApiModelProperty(value = "编码")
    @TableField("code")
    @Column(name="code")
    private String code;

    @ApiModelProperty(value = "数据源名称")
    @TableField("name")
    @Column(name="name")
    private String name;

    @ApiModelProperty(value = "用户名,密码,url,driverClassName,还有其他参数等等,json字符串")
    @TableField("data_src_property")
    @Column(name="data_src_property")
    private String dataSrcProperty;

    @ApiModelProperty(value = "数据源类型id")
    @TableField("dyna_data_src_type_id")
    @Column(name="dyna_data_src_type_id")
    private Long dynaDataSrcTypeId;


    /**
     * 获取[id]
     * @return  id :[主键]
     */
    public Long getId() {
        return id;
    }
    /**
     * 设置[id]
     * @param  id :[主键]
     */
    public DataSrc setId(Long id) {
        this.id = id;
        return this;
    }

    /**
     * 获取[version]
     * @return  version :[版本]
     */
    public Integer getVersion() {
        return version;
    }
    /**
     * 设置[version]
     * @param  version :[版本]
     */
    public DataSrc setVersion(Integer version) {
        this.version = version;
        return this;
    }

    /**
     * 获取[create_by]
     * @return  createBy :[创建人]
     */
    public Long getCreateBy() {
        return createBy;
    }
    /**
     * 设置[create_by]
     * @param  createBy :[创建人]
     */
    public DataSrc setCreateBy(Long createBy) {
        this.createBy = createBy;
        return this;
    }

    /**
     * 获取[create_by_name]
     * @return  createByName :[创建人名称]
     */
    public String getCreateByName() {
        return createByName;
    }
    /**
     * 设置[create_by_name]
     * @param  createByName :[创建人名称]
     */
    public DataSrc setCreateByName(String createByName) {
        this.createByName = createByName;
        return this;
    }

    /**
     * 获取[create_time]
     * @return  createTime :[创建时间]
     */
    public LocalDateTime getCreateTime() {
        return createTime;
    }
    /**
     * 设置[create_time]
     * @param  createTime :[创建时间]
     */
    public DataSrc setCreateTime(LocalDateTime createTime) {
        this.createTime = createTime;
        return this;
    }

    /**
     * 获取[last_up_by]
     * @return  lastUpBy :[更新人]
     */
    public Long getLastUpBy() {
        return lastUpBy;
    }
    /**
     * 设置[last_up_by]
     * @param  lastUpBy :[更新人]
     */
    public DataSrc setLastUpBy(Long lastUpBy) {
        this.lastUpBy = lastUpBy;
        return this;
    }

    /**
     * 获取[last_up_by_name]
     * @return  lastUpByName :[更新人名称]
     */
    public String getLastUpByName() {
        return lastUpByName;
    }
    /**
     * 设置[last_up_by_name]
     * @param  lastUpByName :[更新人名称]
     */
    public DataSrc setLastUpByName(String lastUpByName) {
        this.lastUpByName = lastUpByName;
        return this;
    }

    /**
     * 获取[last_up_time]
     * @return  lastUpTime :[更新时间]
     */
    public LocalDateTime getLastUpTime() {
        return lastUpTime;
    }
    /**
     * 设置[last_up_time]
     * @param  lastUpTime :[更新时间]
     */
    public DataSrc setLastUpTime(LocalDateTime lastUpTime) {
        this.lastUpTime = lastUpTime;
        return this;
    }

    /**
     * 获取[is_del]
     * @return  isDel :[是否删除(1/0)默认0]
     */
    public Integer getIsDel() {
        return isDel;
    }
    /**
     * 设置[is_del]
     * @param  isDel :[是否删除(1/0)默认0]
     */
    public DataSrc setIsDel(Integer isDel) {
        this.isDel = isDel;
        return this;
    }

    /**
     * 获取[remark]
     * @return  remark :[备注]
     */
    public String getRemark() {
        return remark;
    }
    /**
     * 设置[remark]
     * @param  remark :[备注]
     */
    public DataSrc setRemark(String remark) {
        this.remark = remark;
        return this;
    }

    /**
     * 获取[code]
     * @return  code :[编码]
     */
    public String getCode() {
        return code;
    }
    /**
     * 设置[code]
     * @param  code :[编码]
     */
    public DataSrc setCode(String code) {
        this.code = code;
        return this;
    }

    /**
     * 获取[name]
     * @return  name :[数据源名称]
     */
    public String getName() {
        return name;
    }
    /**
     * 设置[name]
     * @param  name :[数据源名称]
     */
    public DataSrc setName(String name) {
        this.name = name;
        return this;
    }

    /**
     * 获取[data_src_property]
     * @return  dataSrcProperty :[用户名,密码,url,driverClassName,还有其他参数等等,json字符串]
     */
    public String getDataSrcProperty() {
        return dataSrcProperty;
    }
    /**
     * 设置[data_src_property]
     * @param  dataSrcProperty :[用户名,密码,url,driverClassName,还有其他参数等等,json字符串]
     */
    public DataSrc setDataSrcProperty(String dataSrcProperty) {
        this.dataSrcProperty = dataSrcProperty;
        return this;
    }

    /**
     * 获取[dyna_data_src_type_id]
     * @return  dynaDataSrcTypeId :[数据源类型id]
     */
    public Long getDynaDataSrcTypeId() {
        return dynaDataSrcTypeId;
    }
    /**
     * 设置[dyna_data_src_type_id]
     * @param  dynaDataSrcTypeId :[数据源类型id]
     */
    public DataSrc setDynaDataSrcTypeId(Long dynaDataSrcTypeId) {
        this.dynaDataSrcTypeId = dynaDataSrcTypeId;
        return this;
    }

}

6,谈到数据来源,那肯定少不了,不同的连接池类型,以下是数据源类型实体

/**
 * <p>
 * 表名:[dyna_data_src_type],数据源类型表 druidDataSource,com.alibaba.druid.pool.DruidDataSourc 实体类
 * </p>
 * @author 
 * @since 2020-10-24
 */
@Entity
@Table(name="data_src_type")
@JsonIgnoreProperties(value = { "hibernateLazyInitializer", "handler" })
@TableName("data_src_type")
@ApiModel(value="DataSrcType对象", description="数据源类型表 druidDataSource,com.alibaba.druid.pool.DruidDataSourc")
public class DataSrcType extends Model<DataSrcType> {

    @ApiModelProperty(value = "主键")
    @TableId(value = "id", type = IdType.ID_WORKER)
    @Id
    @Column(name="id")
    private Long id;

    @ApiModelProperty(value = "版本")
    @TableField("version")
    @Column(name="version")
    @com.baomidou.mybatisplus.annotation.Version
    @javax.persistence.Version
    private Integer version;

    @ApiModelProperty(value = "创建人")
    @TableField(value = "create_by", fill = FieldFill.INSERT)
    @Column(name="create_by")
    private Long createBy;

    @ApiModelProperty(value = "创建人名称")
    @TableField("create_by_name")
    @Column(name="create_by_name")
    private String createByName;

    @ApiModelProperty(value = "创建时间")
    @TableField(value = "create_time", fill = FieldFill.INSERT)
    @Column(name="create_time")
    private LocalDateTime createTime;

    @ApiModelProperty(value = "更新人")
    @TableField(value = "last_up_by", fill = FieldFill.INSERT_UPDATE)
    @Column(name="last_up_by")
    private Long lastUpBy;

    @ApiModelProperty(value = "更新人名称")
    @TableField("last_up_by_name")
    @Column(name="last_up_by_name")
    private String lastUpByName;

    @ApiModelProperty(value = "更新时间")
    @TableField(value = "last_up_time", fill = FieldFill.INSERT_UPDATE)
    @Column(name="last_up_time")
    private LocalDateTime lastUpTime;

    @ApiModelProperty(value = "是否删除(1/0)默认0")
    @TableField("is_del")
    @Column(name="is_del")
    @TableLogic
    private Integer isDel;

    @ApiModelProperty(value = "备注")
    @TableField("remark")
    @Column(name="remark")
    private String remark;

    @ApiModelProperty(value = "编码")
    @TableField("code")
    @Column(name="code")
    private String code;

    @ApiModelProperty(value = "类型名称")
    @TableField("name")
    @Column(name="name")
    private String name;

    @ApiModelProperty(value = "类名")
    @TableField("class_name")
    @Column(name="class_name")
    private String className;


    /**
     * 获取[id]
     * @return  id :[主键]
     */
    public Long getId() {
        return id;
    }
    /**
     * 设置[id]
     * @param  id :[主键]
     */
    public DataSrcType setId(Long id) {
        this.id = id;
        return this;
    }

    /**
     * 获取[version]
     * @return  version :[版本]
     */
    public Integer getVersion() {
        return version;
    }
    /**
     * 设置[version]
     * @param  version :[版本]
     */
    public DataSrcType setVersion(Integer version) {
        this.version = version;
        return this;
    }

    /**
     * 获取[create_by]
     * @return  createBy :[创建人]
     */
    public Long getCreateBy() {
        return createBy;
    }
    /**
     * 设置[create_by]
     * @param  createBy :[创建人]
     */
    public DataSrcType setCreateBy(Long createBy) {
        this.createBy = createBy;
        return this;
    }

    /**
     * 获取[create_by_name]
     * @return  createByName :[创建人名称]
     */
    public String getCreateByName() {
        return createByName;
    }
    /**
     * 设置[create_by_name]
     * @param  createByName :[创建人名称]
     */
    public DataSrcType setCreateByName(String createByName) {
        this.createByName = createByName;
        return this;
    }

    /**
     * 获取[create_time]
     * @return  createTime :[创建时间]
     */
    public LocalDateTime getCreateTime() {
        return createTime;
    }
    /**
     * 设置[create_time]
     * @param  createTime :[创建时间]
     */
    public DataSrcType setCreateTime(LocalDateTime createTime) {
        this.createTime = createTime;
        return this;
    }

    /**
     * 获取[last_up_by]
     * @return  lastUpBy :[更新人]
     */
    public Long getLastUpBy() {
        return lastUpBy;
    }
    /**
     * 设置[last_up_by]
     * @param  lastUpBy :[更新人]
     */
    public DataSrcType setLastUpBy(Long lastUpBy) {
        this.lastUpBy = lastUpBy;
        return this;
    }

    /**
     * 获取[last_up_by_name]
     * @return  lastUpByName :[更新人名称]
     */
    public String getLastUpByName() {
        return lastUpByName;
    }
    /**
     * 设置[last_up_by_name]
     * @param  lastUpByName :[更新人名称]
     */
    public DataSrcType setLastUpByName(String lastUpByName) {
        this.lastUpByName = lastUpByName;
        return this;
    }

    /**
     * 获取[last_up_time]
     * @return  lastUpTime :[更新时间]
     */
    public LocalDateTime getLastUpTime() {
        return lastUpTime;
    }
    /**
     * 设置[last_up_time]
     * @param  lastUpTime :[更新时间]
     */
    public DataSrcType setLastUpTime(LocalDateTime lastUpTime) {
        this.lastUpTime = lastUpTime;
        return this;
    }

    /**
     * 获取[is_del]
     * @return  isDel :[是否删除(1/0)默认0]
     */
    public Integer getIsDel() {
        return isDel;
    }
    /**
     * 设置[is_del]
     * @param  isDel :[是否删除(1/0)默认0]
     */
    public DataSrcType setIsDel(Integer isDel) {
        this.isDel = isDel;
        return this;
    }

    /**
     * 获取[remark]
     * @return  remark :[备注]
     */
    public String getRemark() {
        return remark;
    }
    /**
     * 设置[remark]
     * @param  remark :[备注]
     */
    public DataSrcType setRemark(String remark) {
        this.remark = remark;
        return this;
    }

    /**
     * 获取[code]
     * @return  code :[编码]
     */
    public String getCode() {
        return code;
    }
    /**
     * 设置[code]
     * @param  code :[编码]
     */
    public DataSrcType setCode(String code) {
        this.code = code;
        return this;
    }

    /**
     * 获取[name]
     * @return  name :[类型名称]
     */
    public String getName() {
        return name;
    }
    /**
     * 设置[name]
     * @param  name :[类型名称]
     */
    public DataSrcType setName(String name) {
        this.name = name;
        return this;
    }

    /**
     * 获取[class_name]
     * @return  className :[类名]
     */
    public String getClassName() {
        return className;
    }
    /**
     * 设置[class_name]
     * @param  className :[类名]
     */
    public DataSrcType setClassName(String className) {
        this.className = className;
        return this;
    }

}

7,有了可配置的实体,就到了初始化动态数据源&创建新数据源&切换数据源,继承AbstractRoutingDataSource.

切换数据源changeDataSource(rpSqlCfg);

private void changeDataSource(RpSqlCfg rpSqlCfg) throws Exception {
        String sysCodeExt=rpSqlCfg.getTenantId()+"&"+rpSqlCfg.getOrgId()+"&"+rpSqlCfg.getSysCode();
        String key=ClientDyna.getDbnaDSrcKey(sysCodeExt,rpSqlCfg.getModelCode(),rpSqlCfg.getDataSrcId());
        boolean checkFlag=ClientDyna.check(sysCodeExt,
                rpSqlCfg.getModelCode(),rpSqlCfg.getDataSrcId());
        if(checkFlag){
            logger.error("数据源实体不存在内存中,需要加载");
            //不存在内存中,需要加载
            ReturnDto<DataSrcModRelV> relVReturnDto=dataSrcModRelVFeignClient.getDSMRV(rpSqlCfg.getTenantId(),rpSqlCfg.getOrgId(),rpSqlCfg.getSysCode(),
                    rpSqlCfg.getModelCode(),rpSqlCfg.getDataSrcId());
            DataSrcModRelV dataSrcModRelV=relVReturnDto.getData();
            if(dataSrcModRelV==null){
                throw  new Exception("没找到数据源相关信息!");
            }
            ClientDyna.addMap(dataSrcModRelV);//添加缓存
            dynaRoutingDataSource.createDataSource(sysCodeExt, dataSrcModRelV.getModelCode(),dataSrcModRelV.getDataSrcId());//创建数据源
        }else{
            logger.error("数据源实体存在内存中,不需要加载");
        }
        dynaRoutingDataSource.selectDataSource(key);//切换数据源
    }

8,创建数据源 

public  Object createDataSource(String sysCode,String modelCode,Long dataSrcId) throws Exception {
        String key=ClientDyna.getDbnaDSrcKey(sysCode,modelCode, dataSrcId);
        return createDataSource(key);
    }
	
public static  Object createDataSource(String key) throws Exception {
		 DataSrcModRelV vo = getByKey(key);
	    // Object ds = null;
	     if(vo != null) {	     
	    	// System.out.println("vo.getClassName()="+vo.getClassName());
	    	 //System.out.println("vo.getDataSrcProperty()="+vo.getDataSrcProperty());
			 logger.error("vo.getClassName()="+vo.getClassName());
			 logger.error("vo.getDataSrcProperty()="+vo.getDataSrcProperty());
	    	 Class cc=Class.forName(vo.getClassName());
	    	 Object c =JSONUtil.readObject(vo.getDataSrcProperty(), cc);
	         return c;
	     } else {
	         throw new Exception("当前 cache not exists datasource[createDataSource]");
	     }
	 }

9,更改当前数据源 

public Object selectDataSource(String key) throws Exception {
        if (!this.targetDataSources.containsKey(key)) {
            Object o=this.createDataSource(key);
            DBContextHolder.setDBType(key);
            return o;
        }
        DBContextHolder.setDBType(key);
        return this.targetDataSources.get(key);
    }

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------

一键部署及管理app

异界:

[国服] 天秤座公会战全阶段作业-公主连接自动刀auto

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值