当前位置: 首页 > article >正文

Spring Boot 配置 Mybatis 读写分离

JPA 的读写分离配置不能应用在 Mybatis 上, 所以 Mybatis 要单独处理

为了不影响原有代码, 使用了增加拦截器的方式, 在拦截器里根据 SQL 的 CRUD 来路由到不同的数据源

需要单独增加Mybatis的配置

@Configuration
public class MyBatisConfig {
    @Bean
    public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
        SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
        sessionFactory.setDataSource(dataSource);

        // 注册插件
        sessionFactory.setPlugins(new Interceptor[]{new DataSourceInterceptor()});

        return sessionFactory.getObject();
    }
}

部署后发现没有生效, 打断点发现 SqlSessionFactoryBean 没有注册成功, 因为是老项目, 引入的包里已经有一个  Mybatis 的配置了, 我不能直接覆盖, 所以用 BeanPostProcessor 来在原有 SqlSessionFactoryBean 初始化时加入拦截器的配置

@Configuration
public class MyBatisConfig {
    @Bean
    @ConditionalOnBean(name="routingDataSource")
    public BeanPostProcessor sqlSessionFactoryBeanPostProcessor(@Qualifier("routingDataSource") DataSource routingDataSource) {
        return new BeanPostProcessor() {
            @Override
            public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
                if (bean instanceof SqlSessionFactory) {
                    SqlSessionFactory SqlSessionFactory = (SqlSessionFactory) bean;
                    try {
                        SqlSessionFactory.getConfiguration().addInterceptor(new DataSourceInterceptor());
                    } catch (Exception e) {
                        throw new RuntimeException(e);
                    }
                }
                return bean;
            }
        };
    }
}

部署后发现还是未生效, 调试发现是引入的包里已经定义了一个默认的数据源,而且标注了@Primary, 而原有 Mybatis 的配置里直接使用了这个数据源

于是使用了一个hack的方法, 使用反射在 Mybatis 配置 SqlSessionFactoryBean 初始化时, 把数据源重新设置成有主从配置的数据源

@Configuration
public class MyBatisConfig {
    @Bean
    @ConditionalOnBean(name="routingDataSource")
    public BeanPostProcessor sqlSessionFactoryBeanPostProcessor(@Qualifier("routingDataSource") DataSource routingDataSource) {
        return new BeanPostProcessor() {
@Override
            public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
                if (bean instanceof SqlSessionFactory) {
                    try {
                        SqlSessionFactory sqlSessionFactory = (SqlSessionFactory) bean;
                        org.apache.ibatis.session.Configuration configuration = sqlSessionFactory.getConfiguration();

                        // 使用反射或其他方式修改配置中的数据源
                        Field dataSourceField = configuration.getEnvironment().getClass().getDeclaredField("dataSource");
                        dataSourceField.setAccessible(true);
                        dataSourceField.set(configuration.getEnvironment(), routingDataSource);
                    } catch (Exception e) {
                        throw new BeansException("Failed to modify SqlSessionFactory", e) {};
                    }

                }
                return bean;
            }
        };
    }
}

再次部署测试通过


http://www.kler.cn/a/542957.html

相关文章:

  • docker 安装 Prometheus、Node Exporter 和 Grafana
  • docker使用dockerfile打包镜像(docker如何打包)
  • SpringBootWeb三层架构分层解耦
  • 华为openEuler部署docker
  • SwiftUI 中 .overlay 两种写法的区别及拓展
  • 掌握正则表达式_模式匹配的艺术
  • 【机器学习案列】车辆二氧化碳排放量预测
  • Redis哨兵模式相关问题及解决方案
  • <tauri><rust><GUI>基于rust和tauri的图片显示程序(本地图片的加载、显示、保存)
  • Qt QOpenGLFunctions详解
  • AF3 drmsd函数解读
  • .Net使用EF Core框架如何连接Oracle
  • JVM-Java虚拟机
  • 在postman中设置环境变量和全局变量以及五大常用响应体断言
  • 【C#零基础从入门到精通】(十四)——面向对象三大特征C#封装详解
  • 二叉树、平衡二叉树、B树与B+树的区别与应用
  • redis的数据结构介绍(string
  • 心脏滴血漏洞复现(CVE-2014-0160)
  • 备战蓝桥杯:双指针(滑动窗口)算法之逛花展
  • SpringBoot分布式开发依赖项中,除了myql、redis,都要哪些依赖项是需要本地安装软件并开启服务的?
  • 蓝桥杯---N字形变换(leetcode第6题)题解
  • IDEA中列举的是否是SpringBoot的依赖项的全部?在哪里能查到所有依赖项,如何开发自己的依赖项让别人使用
  • Django:构建高效Web应用的强大框架
  • Idea集成deepseek生成代码
  • ffmpeg -hwaccels
  • 用 TDD 构建 Rust 命令行搜索功能:以 minigrep 为例