三种方式切换数据源

最后更新:2023-12-21 19:07:44 | 状态:未完成
  1. DataSourceHolder.setDataSource("crm")切换数据源,再调用service.query等方法操作相应的数据库
    切换完成后,数据源会一直操持在crm
    如果线程共享的话,不要用这种方式,(如springmvc会默认开启线程池)
    注意:这个方式在8.7.1及之后的版本中取消了,参考【为什么取消了DynamicDataSource/ThreadLocal切换数据源的方式
  2. service.query("<crm>USER");在表名前添加数据源名称
    这种方式切换只针对当前查询有效,查询完成后会切换回原来的数据源(不一定是默认数据源)
  3. 通过ServiceProxy返回数据源对应的service
    AnylineService crmService = ServiceProxy.service("crm"); //返回crm数据源对应的service
    AnylineService defService = ServiceProxy.service() //返回默认默认数据源对应的service
    再通过返回的crmService操作crm数据库,通过defService操作默认的simple数据库
    注意第3种方式返回的service实例只能操作固定的数据源不可以切换

8.7.1之后就没有切换数据源了,实际上是切换的整个运行时环境,service,adapter,jdbc等一整套的全切换。


注册数据源请参考【五种方式注册数据源】和【临时数据源
以上前两种方式使用通用AnylineService实例 通常是用这种方式注入到controller中
@Autowired(required = false)
@Qualifier("anyline.service")
protected AnylineService service;
前1种方式比较方便,但是如果线程被复用时可能会混淆数据源,所以推荐第三种方式,隔离性更强,不容易混淆

以下数据源配置,3个数据源(默认simple+crm+sso)
 spring.datasource.url=jdbc:mysql://localhost:3306/simple
 spring.datasource.list=crm,sso
 spring.datasource.crm.url=jdbc:mysql://localhost:3306/crm
 spring.datasource.sso.url=jdbc:mysql://localhost:3306/sso

以上配置文件会生成4个service
1.common service(bean.id=anyline.service)  : (8.7.1后这个禁用了)用来操作以上3个数据源(运行过程中可随时切换操作哪个数据源),如果没有配置多数据源,用来操作数据库的就是这个service是系统启动时自动初始化的那个service,也就是Controller中注入的service
2.default service(bean.id=anyline.service.default) : 用来操作默认的simple数据源(spring.datasource.url=...)(只有出现多个数据源时才会实例化 default service)
3.crm service(bean.id=anyline.service.crm): 用来操作crm数据源(spring.datasource.crm.url=...)
4.sso service(bean.id=anyline.service.sso): 用来操作sso数据源(spring.datasource.sso.url=...)
出现多个数据源时会实例化多个AnylineService,JdbcTemplate,DataSource所以在注入时注意需要根据name注入,如:

@Autowired
@Qualifier("anyline.service.crm")

protected AnylineService service;


下面这样会抛出异常,因为有多个匹配的service
@Autowired(required = false)
@Qualifier
protected AnylineService service;


如果配置了多数据源,还不想生成多个service(只生成一个comon service)
可以通过ConfigTable.IS_MULTIPLE_SERVICE=false配置或anyline.multiple-service=false

jdbctemplate实例名 anyline.jdbc.template.${数据源名称}
dao实例名 anyline.dao.${数据源名称}
service实例名 anyline.service.${数据源名称}


注意:这里说的common service与default service的区别
default service:
是一个bean name=default的service 对应了默认数据源(spring.datasource.url=jdbc:mysql://localhost:3306/simple
)
而其他的service是在配置文件中指定了名称的(就是数据源的名称,如下面配置文件中的crm,sso)
这几个service都只用来操作某一个固定的数据源,运行过程中不能切换

common service:
如果没有用到多数据源的话 这个common service就是Controller中通过注解注入的那个service
ServiceProxy.query()内部调用的service是也是这个service
commonm service 可以通过DataSourceHolder切换数据源来操作多个数据库

为什么common和default不合成一个(8.7.1后common禁用了)
因为common service在运行过程中会切换数据源,这个切换在当前线程中全局有效
如果合成一个的话ServiceProxy.service()返回common service就不确定当前正在操作哪个数据源了,
而设计的初衷是希望返回一个 default service只操作一个固定的数据源


为什么default service、crm service、sso service不能切换数据源
因为切来切去容易混淆,运行过程中切换了数据源会影响当前线程中的其他方法,导致编码过程中不确定当前在操作的是哪个数据源,容易误操作。
如果需要切换的话用common service就可以。


//设置固定数据源,在这之后执行的查询都是查询的crm数据源
DataSourceHolder.setDataSource("crm");
//这里查询的的crm数据源,执行完成后还保持crm数据源
DataSet set = service.querys("crm_customer");


//这里查询erp数据源中的表,执行完成后切换回执行之前的crm数据源,注意并不是默认数据源
set = service.querys("<erp>mm_material");

//这里查询的的crm数据源,而不需要指定<crm>,因为之前已通过DataSourceHolder固定设置了crm数据源
set = service.querys("crm_customer");

最近更新 搜索 提交