收到一个用户需求要求时时展现填报信息,之前项目使用的数据库是MySQL
,但是由于数据量较大而且计算过程复杂,所以决定将数据放到Oracle
中利用存储过程计算,这样就需要项目同时连接Oracle
和MySQL
数据库。下边简单总结下分库分表
分表
当一个表的数据量很大以后,业务上就需要根据规则对数据库进行水平切分,如注册用户表user_01
,user_02
等,但是当数据库表进行切分以后,程序就需要根据规格进行相应的处理。利用Mybatis
的interceptor
可以实现根据路由规则去操作相应的数据库,开源的有Shardbatis
实现。但是sharding
只能区分一个数据源中的不同表,并不能根据规则切换数据源。
分库
如果想连接多个数据库,需要配置两个数据源,如
|
|
- 利用
AbstractRoutingDataSource
.
在配置文件中加入DynamicDataSource
配置,其中可以配置多个数据源链接和默认的链接
|
|
然后继承AbstractRoutingDataSource
,该方法中实现数据库的动态切换。
|
|
定义一个可以设置当前线程的变量的工具类,用于设置对应的数据源名称。由于Spring的Bean是单例的,需要将数据源放入ThreadLocal
中来避免线程安全的问题。
也可以利用AOP
+Annotation
来实现基于注解的数据库动态切换。
- 直接配置两个数据源。
这种方式简单粗暴,配置多个数据源直接访问不同的数据库,但是数据库的事务会存在问题,不能同时保证多个数据库的事务。配置时遇到了spring-mybatis
的一个大坑。
天真的以为同时配置两套datasource
,sessionFactory
,transaction
,mapperscannerconfigurer
就能用了,如
|
|
但是并没有。。。一直抱一个Mapped Statements collection does not contain value for
的错误,直接将mybatis的xml放到另一个数据源下就会报表不存在的错误,事实证明配置的Oracle数据源在Mybatis中并没有生效。在stackoverflow
上也并没有找到相关问题的解。无意中看到一篇文章,原文地址
https://www.iflym.com/index.php/code/201211010001.html
才发现spring-mybatis
的一个大坑。原文指出在MapperFactoryBean
的父类SqlSessionDaoSupport
你绝对想不到,因为经过Autowired的处理,MapperFactoryBean即会运行setSqlSessionFactory方法,也会运行setSqlSessionTemplate方法。而更让人郁闷的是,你设置的sqlSessionFactoryBeanName根本没有用。这来自于内部,自以为是的externalSqlSession变量。当此变量为true时,setSqlSessionFactory方法会直接返回。因为,setSqlSessionTemplate会比属性注入的applyPropertyValues更先运行,这一切是不是很让人郁闷。
所以在xml中配置文件改成
问题解决了!!!