前面使用spring+mybatis+uncode dal
实现应用与postgresql主从数据库集成实现读写分离
那么在主数据库连接错误的情况下,如何保证在主数据库发生异常情况下任何数据库请求都能够正确执行
并且能够快速的尝试其他数据库
可以有两种方式
1.目前的DynamicDataSource获取数据库连接异常就会立即抛出异常,不会重试
对dal的cn.uncode.dal.datasource.DynamicDataSource类进行扩展
重写其getConnection方法
在获得datasource的connection错误时,立即切换到其他数据库并重新获取其连接,
指定mybatis使用这种新的datasource
2.实现mybatis的拦截器,
这种方式可以指定哪类方法访问哪些数据库,并且在获取数据库连接错误的时候
可以尝试获取其他数据库的连接
需要做以下修改
a.定义新的inteceptor
Mybatis拦截器只能拦截四种类型的接口:Executor、StatementHandler、ParameterHandler和ResultSetHandler。
这是在Mybatis的Configuration中写死了的,如果要支持拦截其他接口就需要我们重写Mybatis的Configuration。
Mybatis可以对这四个接口中所有的方法进行拦截。
参照http://haohaoxuexi.iteye.com/blog/1851081
拦截器中可以根据方法名来设定route
(例如下面定义拦截器对所有executor的query方法进行拦截,设定路由为读,那么后面获取
连接只会从从数据库列表中获取
并且设定重试机制)
@Intercepts( @Signature(method = "query", type = Executor.class, args = {
MappedStatement.class, Object.class, RowBounds.class,
ResultHandler.class }))
public class MyInterceptor implements Interceptor {
@Override
public Object intercept(Invocation invocation) throws Throwable {
int count=0;
DBContextHolder.switchRead()
while(count<=3) {
try {
return invocation.proceed();
} catch (Exception e) {
count=count+1;
}
}
return invocation.proceed();
}
@Override
public Object plugin(Object o) {
return Plugin.wrap(o, this);
}
@Override
public void setProperties(Properties properties) {
}
}
2.在mybatis配置文件中注册新的interceptor
在mybatis-config.xml中指定拦截器
<configuration>
<plugins>
<plugin interceptor="<包名.MyInterceptor"></plugin>
</plugins>
</configuration>
3.为了能够快速切换数据源,
需要指定druiddatasource的
jdbc.pool.maxWait = 1000
这样1s内连接不成功,就会抛出异常,拦截器捕获到异常就会重试
4.原有使用mybatis dao的代码不用做任何修改