如何区分管理员登录库与产品库 解决产品数据错写入用户库问题
多数据源串库问题修复方案
问题表现
业务配置两套独立数据库:
users库:专门存储管理员账号、权限数据,承载登录鉴权逻辑databengkel库:专门存储产品业务数据,承载产品增删改查逻辑
测试产品新增接口时出现路由异常:提交的产品数据未写入目标databengkel库,错误写入users库,需要实现两个数据库的逻辑隔离。
核心原因
串库本质是多数据源路由规则未生效,常见触发场景:
- 数据源Bean优先级配置错误,默认主数据源被所有业务逻辑无差别调用
- 业务Dao/Mapper的扫描规则未做路径拆分,所有数据库操作都被默认数据源的SqlSessionFactory托管
- 数据源切换注解和事务注解顺序冲突,事务提前锁定默认数据源连接,导致后续切换逻辑失效
- 业务方法未指定对应数据源标识,默认走主库连接
分步配置实现(以SpringBoot+MyBatis场景为例,其他框架逻辑通用)
1. 拆分数据源连接配置
在配置文件中分开定义两个数据源的连接参数,不要混用默认配置项:
spring: datasource: # 鉴权库连接配置 users: jdbc-url: jdbc:mysql://数据库地址:3306/users?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai username: 账号 password: 密码 driver-class-name: com.mysql.cj.jdbc.Driver # 业务库连接配置 databengkel: jdbc-url: jdbc:mysql://数据库地址:3306/databengkel?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai username: 账号 password: 密码 driver-class-name: com.mysql.cj.jdbc.Driver
注意:自定义多数据源场景下,连接地址参数必须用
jdbc-url作为键名,不能用默认的url,否则会被SpringBoot默认数据源自动装配逻辑抢占,导致自定义配置失效。
2. 分数据源配置独立托管规则
将两个数据源的Dao、Mapper、事务管理器完全拆分托管,避免交叉扫描:
- 所有鉴权相关的Mapper统一放在
com.项目包名.mapper.users路径下,绑定users数据源 - 所有产品业务相关的Mapper统一放在
com.项目包名.mapper.bengkel路径下,绑定databengkel数据源
分别编写两个数据源的配置类:users库作为默认主数据源,配置类代码:
@Configuration @MapperScan(basePackages = "com.项目包名.mapper.users", sqlSessionFactoryRef = "usersSqlSessionFactory") public class UsersDataSourceConfig { @Bean("usersDataSource") @Primary // 标记为默认主数据源 @ConfigurationProperties(prefix = "spring.datasource.users") public DataSource usersDataSource(){ return DataSourceBuilder.create().build(); } @Bean("usersSqlSessionFactory") @Primary public SqlSessionFactory usersSqlSessionFactory(@Qualifier("usersDataSource") DataSource dataSource) throws Exception { SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean(); sessionFactory.setDataSource(dataSource); // 绑定users库对应的Mapper XML路径 sessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mapper/users/*.xml")); return sessionFactory.getObject(); } @Bean("usersTransactionManager") @Primary public DataSourceTransactionManager usersTransactionManager(@Qualifier("usersDataSource") DataSource dataSource){ return new DataSourceTransactionManager(dataSource); } }
databengkel业务库配置类代码:
@Configuration @MapperScan(basePackages = "com.项目包名.mapper.bengkel", sqlSessionFactoryRef = "bengkelSqlSessionFactory") public class BengkelDataSourceConfig { @Bean("bengkelDataSource") @ConfigurationProperties(prefix = "spring.datasource.databengkel") public DataSource bengkelDataSource(){ return DataSourceBuilder.create().build(); } @Bean("bengkelSqlSessionFactory") public SqlSessionFactory bengkelSqlSessionFactory(@Qualifier("bengkelDataSource") DataSource dataSource) throws Exception { SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean(); sessionFactory.setDataSource(dataSource); // 绑定databengkel库对应的Mapper XML路径 sessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mapper/bengkel/*.xml")); return sessionFactory.getObject(); } @Bean("bengkelTransactionManager") public DataSourceTransactionManager bengkelTransactionManager(@Qualifier("bengkelDataSource") DataSource dataSource){ return new DataSourceTransactionManager(dataSource); } }
3. 配置校验&避坑
配置完成后按以下点逐一校验,避免串库问题复现:
- 检查产品新增逻辑对应的Mapper类、XML文件是否放在
databengkel对应的扫描路径下,不要错放到users库的扫描目录 - 如果使用动态数据源注解(如
@DS)实现切换,注解要加在实现类的public方法上,不要加在接口层面;如果方法上同时使用@Transactional注解,必须手动指定事务管理器为对应库的事务管理器,比如产品新增方法要指定@Transactional(transactionManager = "bengkelTransactionManager"),否则事务会默认获取主数据源连接,导致数据源切换失效 - 启动服务后查看初始化日志,确认两个数据源的连接地址分别对应正确的库名,没有配置错连接参数
- 接口测试时分别查询两个库的对应表,确认管理员鉴权相关操作写入
users库,产品相关操作写入databengkel库,隔离逻辑生效。
内容的提问来源于stack exchange,提问作者hi brian
相关产品推荐
相关产品推荐

