谈谈利用Mybatis分库分表
Posted ssskkk
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了谈谈利用Mybatis分库分表相关的知识,希望对你有一定的参考价值。
分库
在分库的时候 有时候为了方便 一些表需要存放所有库的信息,称为全局库。如:用户表存放所有的用户。
此时分库的思路 数据库分为全局库和业务库,其中业务库又分为N多个库,全局库只放个别表方便开发。
这个时候 就需要一个全局DAO,此时我们的Mybatis就需要支持两个DAO
两个DAO(bizDao和globalDao)就需要有两个sqlSessionFactory,bizSqlSessionFactory和globalSqlSessionFactory和两个事物管理器transactionManager
根据请求动态指定业务库DataSource
分库就是一个项目有多个数据库,对Myabtis来说就有多个数据源(dataSource)根据你的请求 判断应该查询哪个库 从而指定动态指定哪个数据源
可以继承Spring的AbstractRoutingDataSource重写接口中determineCurrentLookupKey()根据业务需求返回当前的dbkey(哪个库1、2、3、4。。。)
全局库和业务库事物管理器
因为事物是基于Service的,所以Service也建议分为全局Service和业务Service,根据Service类型(建议配个AOP全局处理 放到ThreadLocal中)
实现PlatformTransactionManager接口,接口中getTransaction()方法可以动态的返回指定的事物管理器(从上面的ThreadLocal中拿到当前的事物管理器)
思考:为什么AbstractRoutingDataSource中多个DataSource不需要动态配置事物管理器?
总结:业务库和全局库有两个不同的DataSource,其中业务库的DataSource继承Spring的AbstractRoutingDataSource,
Spring又分为了N个DataSource(对bizSqlSessionFactory而言 只有一个RoutingDataSource,RoutingDataSource里面有一个数据源集合)
全局的globalSqlSessionFactory也可以当bizSqlSessionFactory中的AbstractRoutingDataSource的一个属性 这么做虽然减少了配置,但是开发不直观。
分表
上面的分库的思路就是动态指定DateSource和TransactionManager
分表:就是在Mybatis中写一个拦截器 动态的更改表名
1.拦截器
SqlSessionFactoryBean里面有个private Interceptor[] plugins;属性 可以配置一些拦截器
我们自己定义的拦截器需要实现Interceptor接口
接口需要加以下注解
@Intercepts( @Signature(type = StatementHandler.class, method = "prepare", args = Connection.class) )
2.在拦截器里面 我们需要动态解析SQL和更改SQL
@Intercepts( @Signature(type = StatementHandler.class, method = "prepare", args = Connection.class) ) public class MybatisInterceptor implements Interceptor @Override public Object intercept(Invocation invocation) throws Throwable if (invocation.getTarget() instanceof StatementHandler) RoutingStatementHandler handler = (RoutingStatementHandler) invocation.getTarget(); //通过反射拿到statement对象 StatementHandler delegate = (StatementHandler) ReflectUtil.getFieldValue(handler, "delegate"); BoundSql boundSql = delegate.getBoundSql(); String sql = boundSql.getSql(); String pageSql =sql+" limit 1 ";//操作sql //再通过反射把新sql设置进去 ReflectUtil.setFieldValue(boundSql, "sql", pageSql); return invocation.proceed();
以上是关于谈谈利用Mybatis分库分表的主要内容,如果未能解决你的问题,请参考以下文章