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,说到连接数据库,那当然需要一个静态数据库,用来获取数据库配置数据,然后根据静态数据库的数据库配置数据生成动态数据.
如下是数据库配置实体类
/**
*
* 表名:[data_src],数据源表 实体类
*
* @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 {
@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,谈到数据来源,那肯定少不了,不同的连接池类型,以下是数据源类型实体
/**
*
* 表名:[dyna_data_src_type],数据源类型表 druidDataSource,com.alibaba.druid.pool.DruidDataSourc 实体类
*
* @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 {
@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 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