spring-boot+mybatis多数据源-读写分离

继续上篇文章加点东西玩玩 spring-boot+mybatis多数据源-简化配置过程https://mp.csdn.net/postedit/100708788

有了多数据源,自然要更有意思的切换来玩,单纯的拦截器根据入参中的值进行业务判断然后切换数据源是比较简单的套路,现在来试试如何更优雅的读写分离。

mybatis提供了拦截器插件,牛逼。直接拦截sql语句,如果是读的就切到db2,写的就切到db1.就这个思路

直接上代码

拦截器

@Intercepts({
    @Signature(
        type = StatementHandler.class,
        method = "query",
        args = {Statement.class,ResultHandler.class})
        })
public class MybatisInterceptor implements Interceptor {
    public static final Logger log = LoggerFactory.getLogger(MybatisInterceptor.class);
    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        String sql = ((StatementHandler)invocation.getTarget()).getBoundSql().getSql();
        if(isQuery(sql)){
            DBUtils.setDB("db2");
        }else{
            DBUtils.setDB("db1");
        }
        log.info("execute db:{} sql: {}",DBUtils.getDB(),sql);
        return invocation.proceed();
    }

    private boolean isQuery(String sql){
        return sql.trim().substring(0,10).toLowerCase().contains("select");
    }
    @Override
    public Object plugin(Object target) {
        return Plugin.wrap(target, this);
    }
    @Override
    public void setProperties(Properties properties) {
    }
}


使用Intercepts注解,属性Signature定义拦截的切面type = StatementHandler.class表示根据sql拦截,其实我也不想知道为什么定义了一个 method = "query"就把其他的都拦截到了。

添加一个bean,注入这个拦截器


    @Bean
    public MybatisInterceptor[] mybatisInterceptor() {
        MybatisInterceptor[] ms = {new MybatisInterceptor()};
        return ms;
    }

把拦截器送给SqlSessionFactoryBean

  @Bean
    public SqlSessionFactory sqlSessionFactory() throws Exception {
        SqlSessionFactoryBean sessionFactoryBean = new SqlSessionFactoryBean();
        sessionFactoryBean.setDataSource(dataSource());
        sessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver()
            .getResources("classpath*:mybatis/mapper/*.xml"));
        sessionFactoryBean.setPlugins(mybatisInterceptor());
        return sessionFactoryBean.getObject();
    }

其中**sessionFactoryBean.setPlugins(mybatisInterceptor());**为把拦截器注进去

然后加几个sql测试

public String doTest() {
        System.out.println(userMapper.selectAll());
        userMapper.update();
        userMapper.insert();
        userMapper.delete();
        return "success";
    }

同时取消了DButils里面的日志打印,全部放到拦截器中打印

访问http://localhost:8989/doTest测试
在这里插入图片描述
可以看到,在拦截器里面定义的,select的语句走db2,其他的语句走db1。当db1和2是主从的时候,就可以用来做读写分离了。无聊吧,当然MySQL的读写分离也可以用开源的成型的mycat来做。


版权声明:本文为qq_36270700原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。