Spring集成Mybatis-Plus(适用于非Springboot项目)
在不使用 Spring Boot特性(如自动配置、starter 依赖、@SpringBootApplication 等)的纯 Spring 环境中,集成 MyBatis-Plus 实现多数据源,需通过传统 Spring 配置(JavaConfig 或 XML) 手动定义所有核心组件。以下是具体实现步骤:
一、环境准备(依赖配置)
需引入纯 Spring 核心依赖、MyBatis-Plus 核心包、数据库驱动和连接池(以 Maven 为例),不使用任何 Spring Boot 相关依赖:
xml
<!-- Spring 核心依赖 -->
<dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.3.28</version>
</dependency>
<dependency><groupId>org.springframework</groupId><artifactId>spring-jdbc</artifactId><version>5.3.28</version>
</dependency><!-- MyBatis 核心 -->
<dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.5.13</version>
</dependency>
<!-- MyBatis 与 Spring 集成 -->
<dependency><groupId>org.mybatis</groupId><artifactId>mybatis-spring</artifactId><version>3.0.2</version>
</dependency>
<!-- MyBatis-Plus 核心 -->
<dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-core</artifactId><version>3.5.3.1</version>
</dependency>
<!-- MyBatis-Plus 与 Spring 集成(非 Boot 版) -->
<dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-spring</artifactId><version>2.3.0</version>
</dependency><!-- 数据库驱动(MySQL) -->
<dependency><groupId>com.mysql</groupId><artifactId>mysql-connector-j</artifactId><version>8.0.33</version>
</dependency><!-- 连接池(Hikari) -->
<dependency><groupId>com.zaxxer</groupId><artifactId>HikariCP</artifactId><version>5.0.1</version>
</dependency><!-- 配置文件解析(Spring 支持 properties 解析) -->
<dependency><groupId>org.springframework</groupId><artifactId>spring-context-support</artifactId><version>5.3.28</version>
</dependency>
二、配置文件(properties)
创建 src/main/resources/jdbc.properties 存储多数据源配置:
properties
# 主数据源(master)
master.jdbc.driver=com.mysql.cj.jdbc.Driver
master.jdbc.url=jdbc:mysql://localhost:3306/master_db?useSSL=false&serverTimezone=UTC
master.jdbc.username=root
master.jdbc.password=123456
master.hikari.max-pool-size=10
master.hikari.min-idle=5# 从数据源(slave)
slave.jdbc.driver=com.mysql.cj.jdbc.Driver
slave.jdbc.url=jdbc:mysql://localhost:3306/slave_db?useSSL=false&serverTimezone=UTC
slave.jdbc.username=root
slave.jdbc.password=123456
slave.hikari.max-pool-size=10
slave.hikari.min-idle=5# MyBatis 配置
mybatis.mapper-locations-master=classpath:mapper/master/*.xml
mybatis.mapper-locations-slave=classpath:mapper/slave/*.xml
三、核心配置(JavaConfig)
通过纯 Spring 的 @Configuration 注解配置数据源、MyBatis-Plus 组件和事务管理器,不依赖任何 Spring Boot 类。
1. 配置文件加载
创建配置类加载 jdbc.properties:
java
运行
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
import org.springframework.core.io.ClassPathResource;@Configuration
public class PropertyConfig {// 加载 properties 配置文件@Beanpublic static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {PropertySourcesPlaceholderConfigurer configurer = new PropertySourcesPlaceholderConfigurer();configurer.setLocation(new ClassPathResource("jdbc.properties"));return configurer;}
}
2. 多数据源配置
手动创建 master 和 slave 数据源(基于 HikariCP):
java
运行
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;import javax.sql.DataSource;@Configuration
public class DataSourceConfig {// 主数据源配置@Value("${master.jdbc.driver}")private String masterDriver;@Value("${master.jdbc.url}")private String masterUrl;@Value("${master.jdbc.username}")private String masterUsername;@Value("${master.jdbc.password}")private String masterPassword;@Value("${master.hikari.max-pool-size}")private int masterMaxPoolSize;@Value("${master.hikari.min-idle}")private int masterMinIdle;// 从数据源配置@Value("${slave.jdbc.driver}")private String slaveDriver;@Value("${slave.jdbc.url}")private String slaveUrl;@Value("${slave.jdbc.username}")private String slaveUsername;@Value("${slave.jdbc.password}")private String slavePassword;@Value("${slave.hikari.max-pool-size}")private int slaveMaxPoolSize;@Value("${slave.hikari.min-idle}")private int slaveMinIdle;// 主数据源(@Primary 标注默认数据源)@Primary@Bean(name = "masterDataSource")public DataSource masterDataSource() {HikariConfig config = new HikariConfig();config.setDriverClassName(masterDriver);config.setJdbcUrl(masterUrl);config.setUsername(masterUsername);config.setPassword(masterPassword);config.setMaximumPoolSize(masterMaxPoolSize);config.setMinimumIdle(masterMinIdle);return new HikariDataSource(config);}// 从数据源@Bean(name = "slaveDataSource")public DataSource slaveDataSource() {HikariConfig config = new HikariConfig();config.setDriverClassName(slaveDriver);config.setJdbcUrl(slaveUrl);config.setUsername(slaveUsername);config.setPassword(slavePassword);config.setMaximumPoolSize(slaveMaxPoolSize);config.setMinimumIdle(slaveMinIdle);return new HikariDataSource(config);}
}
3. MyBatis-Plus 核心组件配置(主库)
为 master 数据源配置 SqlSessionFactory、SqlSessionTemplate 和事务管理器:
java
运行
import com.baomidou.mybatisplus.core.MybatisConfiguration;
import com.baomidou.mybatisplus.core.config.GlobalConfig;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionTemplate;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;import javax.sql.DataSource;
import java.io.IOException;@Configuration
// 扫描 master 数据源对应的 Mapper 接口(包路径隔离)
@MapperScan(basePackages = "com.example.mapper.master",sqlSessionFactoryRef = "masterSqlSessionFactory",sqlSessionTemplateRef = "masterSqlSessionTemplate"
)
public class MasterMybatisConfig {@Value("${mybatis.mapper-locations-master}")private String masterMapperLocations;// 注入主数据源private final DataSource masterDataSource;public MasterMybatisConfig(@Qualifier("masterDataSource") DataSource masterDataSource) {this.masterDataSource = masterDataSource;}/*** 配置 master 数据源的 SqlSessionFactory(MyBatis-Plus 核心)*/@Primary@Bean(name = "masterSqlSessionFactory")public SqlSessionFactory masterSqlSessionFactory() throws Exception {MybatisSqlSessionFactoryBean factoryBean = new MybatisSqlSessionFactoryBean();factoryBean.setDataSource(masterDataSource); // 绑定主数据源// 设置 Mapper XML 路径factoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(masterMapperLocations));// MyBatis 核心配置(如下划线转驼峰)MybatisConfiguration configuration = new MybatisConfiguration();configuration.setMapUnderscoreToCamelCase(true);factoryBean.setConfiguration(configuration);// 配置 MyBatis-Plus 插件(如分页插件)MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();interceptor.addInnerInterceptor(new PaginationInnerInterceptor()); // 分页插件factoryBean.setPlugins(interceptor);// MyBatis-Plus 全局配置(如逻辑删除)GlobalConfig globalConfig = new GlobalConfig();globalConfig.getDbConfig().setLogicDeleteField("isDeleted");globalConfig.getDbConfig().setLogicDeleteValue("1");globalConfig.getDbConfig().setLogicNotDeleteValue("0");factoryBean.setGlobalConfig(globalConfig);return factoryBean.getObject();}/*** master 数据源的 SqlSessionTemplate*/@Primary@Bean(name = "masterSqlSessionTemplate")public SqlSessionTemplate masterSqlSessionTemplate() throws Exception {return new SqlSessionTemplate(masterSqlSessionFactory());}/*** master 数据源的事务管理器*/@Primary@Bean(name = "masterTransactionManager")public PlatformTransactionManager masterTransactionManager() {return new DataSourceTransactionManager(masterDataSource);}
}
4. MyBatis-Plus 核心组件配置(从库)
从库配置与主库类似,仅需修改包路径、Bean 名称和数据源引用:
java
运行
import com.baomidou.mybatisplus.core.MybatisConfiguration;
import com.baomidou.mybatisplus.core.config.GlobalConfig;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;import javax.sql.DataSource;@Configuration
// 扫描 slave 数据源对应的 Mapper 接口
@MapperScan(basePackages = "com.example.mapper.slave",sqlSessionFactoryRef = "slaveSqlSessionFactory",sqlSessionTemplateRef = "slaveSqlSessionTemplate"
)
public class SlaveMybatisConfig {@Value("${mybatis.mapper-locations-slave}")private String slaveMapperLocations;// 注入从数据源private final DataSource slaveDataSource;public SlaveMybatisConfig(@Qualifier("slaveDataSource") DataSource slaveDataSource) {this.slaveDataSource = slaveDataSource;}/*** 配置 slave 数据源的 SqlSessionFactory*/@Bean(name = "slaveSqlSessionFactory")public SqlSessionFactory slaveSqlSessionFactory() throws Exception {MybatisSqlSessionFactoryBean factoryBean = new MybatisSqlSessionFactoryBean();factoryBean.setDataSource(slaveDataSource);// 设置从库 Mapper XML 路径factoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(slaveMapperLocations));// MyBatis 配置MybatisConfiguration configuration = new MybatisConfiguration();configuration.setMapUnderscoreToCamelCase(true);factoryBean.setConfiguration(configuration);// 插件配置MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();interceptor.addInnerInterceptor(new PaginationInnerInterceptor());factoryBean.setPlugins(interceptor);// 全局配置GlobalConfig globalConfig = new GlobalConfig();globalConfig.getDbConfig().setLogicDeleteField("isDeleted");factoryBean.setGlobalConfig(globalConfig);return factoryBean.getObject();}/*** slave 数据源的 SqlSessionTemplate*/@Bean(name = "slaveSqlSessionTemplate")public SqlSessionTemplate slaveSqlSessionTemplate() throws Exception {return new SqlSessionTemplate(slaveSqlSessionFactory());}/*** slave 数据源的事务管理器*/@Bean(name = "slaveTransactionManager")public PlatformTransactionManager slaveTransactionManager() {return new DataSourceTransactionManager(slaveDataSource);}
}
5. Spring 容器初始化
创建 Spring 容器启动类(替代 Spring Boot 的 SpringApplication):
java
运行
import org.springframework.context.annotation.AnnotationConfigApplicationContext;public class AppContext {public static void main(String[] args) {// 加载所有配置类AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();context.scan("com.example.config"); // 扫描配置类所在包(如 DataSourceConfig、MasterMybatisConfig 等)context.refresh();System.out.println("Spring 容器初始化完成");}
}
四、使用多数据源
通过包路径隔离实现数据源绑定,主库 Mapper 放在 com.example.mapper.master,从库放在 com.example.mapper.slave。
1. 主库 Mapper 示例
java
运行
package com.example.mapper.master;import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.example.entity.MasterUser;public interface MasterUserMapper extends BaseMapper<MasterUser> {
}
2. 从库 Mapper 示例
java
运行
package com.example.mapper.slave;import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.example.entity.SlaveOrder;public interface SlaveOrderMapper extends BaseMapper<SlaveOrder> {
}
3. 事务使用
在 Service 中通过 @Transactional 的 value 指定事务管理器:
java
运行
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;@Service
public class UserService {private final MasterUserMapper masterUserMapper;// 构造器注入 Mapperpublic UserService(MasterUserMapper masterUserMapper) {this.masterUserMapper = masterUserMapper;}// 使用主库事务管理器@Transactional(value = "masterTransactionManager")public void addUser(MasterUser user) {masterUserMapper.insert(user);}
}
核心原理总结
- 纯 Spring 配置:不依赖 Spring Boot 的自动配置、starter 或
SpringApplication,通过AnnotationConfigApplicationContext手动初始化容器。 - 手动管理依赖:数据源、SqlSessionFactory、事务管理器等核心组件均通过 JavaConfig 手动定义,属性从
properties文件读取。 - 隔离性保证:通过
@MapperScan扫描不同包下的 Mapper 接口,绑定到对应的SqlSessionFactory,实现数据源隔离。 - 兼容性:完全基于 Spring 5 和 MyBatis-Plus 3.x 核心 API,适用于传统 Spring 项目(非 Boot)。
这种方式灵活性极高,可完全掌控多数据源的配置细节,适合不使用 Spring Boot 的传统项目。
