1. MyBatis开发模式演进全景图
作为Java生态中最主流的ORM框架之一,MyBatis经历了从原生模式到与Spring家族深度整合的技术演进。这种演进背后反映的是Java企业级应用开发范式的变迁:
- 原生MyBatis(Pre-Spring时代):需要手动管理SqlSessionFactory生命周期,事务控制通过编程式实现,典型代码如下:
String resource = "mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); try (SqlSession session = sqlSessionFactory.openSession()) { UserMapper mapper = session.getMapper(UserMapper.class); // 业务操作 session.commit(); // 显式提交 }- Spring整合阶段(XML配置时代):通过
SqlSessionFactoryBean将MyBatis纳入Spring IoC容器管理,事务交由Spring声明式事务控制,配置示例:
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource"/> <property name="mapperLocations" value="classpath*:mapper/**/*.xml"/> </bean> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="basePackage" value="com.example.dao"/> </bean>- Spring Boot自动化配置时代:基于starter的约定优于配置原则,只需引入
mybatis-spring-boot-starter依赖,零配置开箱即用:
<dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>3.0.3</version> </dependency>关键演进趋势:配置从代码→XML→注解→自动配置演变;事务管理从手动控制→声明式→自动代理发展;SQL执行从模板代码→动态代理→接口方法演进。
2. 原生MyBatis核心运作机制剖析
2.1 架构核心三要素
- SqlSessionFactoryBuilder:解析XML配置(含全局配置、类型别名、插件等)构建工厂
- SqlSessionFactory:线程安全的工厂对象,生产SqlSession实例
- SqlSession:包含CRUD方法的会话对象,非线程安全需方法级使用
2.2 事务控制实战
原生模式下需手动管理事务边界,典型模式:
SqlSession session = null; try { session = sqlSessionFactory.openSession(false); // 关闭自动提交 UserMapper mapper = session.getMapper(UserMapper.class); mapper.updateUser(user1); mapper.insertLog(log); session.commit(); // 显式提交 } catch (Exception e) { if(session != null) session.rollback(); throw e; } finally { if(session != null) session.close(); }2.3 性能优化要点
- SqlSession管理:推荐使用try-with-resources确保及时关闭
- Mapper代理机制:通过
MapperProxy动态生成接口实现类 - 一级缓存陷阱:同一个SqlSession内相同查询会命中缓存,可能导致脏读
3. Spring整合深度定制方案
3.1 整合核心组件
@startuml [Spring容器] --> [DataSource] [Spring容器] --> [TransactionManager] [Spring容器] --> [SqlSessionFactoryBean] [SqlSessionFactoryBean] --> [MyBatis配置] [Spring容器] --> [MapperScannerConfigurer] @enduml3.2 事务管理增强
通过AOP实现声明式事务,配置示例:
@Configuration @EnableTransactionManagement public class PersistenceConfig { @Bean public PlatformTransactionManager transactionManager(DataSource dataSource) { return new DataSourceTransactionManager(dataSource); } @Bean public SqlSessionFactoryBean sqlSessionFactory(DataSource dataSource) throws IOException { SqlSessionFactoryBean factory = new SqlSessionFactoryBean(); factory.setDataSource(dataSource); factory.setTypeAliasesPackage("com.example.model"); return factory; } }3.3 多数据源解决方案
@Configuration public class MultiDataSourceConfig { @Primary @Bean(name = "masterDataSource") @ConfigurationProperties(prefix = "spring.datasource.master") public DataSource masterDataSource() { return DataSourceBuilder.create().build(); } @Bean(name = "slaveDataSource") @ConfigurationProperties(prefix = "spring.datasource.slave") public DataSource slaveDataSource() { return DataSourceBuilder.create().build(); } @Bean @Primary public SqlSessionFactory masterSqlSessionFactory(@Qualifier("masterDataSource") DataSource dataSource) throws Exception { SqlSessionFactoryBean bean = new SqlSessionFactoryBean(); bean.setDataSource(dataSource); bean.setMapperLocations(new PathMatchingResourcePatternResolver() .getResources("classpath:mapper/master/*.xml")); return bean.getObject(); } @Bean public SqlSessionFactory slaveSqlSessionFactory(@Qualifier("slaveDataSource") DataSource dataSource) throws Exception { // 类似master配置... } }4. Spring Boot整合最佳实践
4.1 自动配置原理
MybatisAutoConfiguration关键逻辑:
- 自动探测
DataSource实例 - 创建
SqlSessionFactory并注入容器 - 扫描
@Mapper接口注册MapperFactoryBean
4.2 定制化配置示例
mybatis: configuration: map-underscore-to-camel-case: true default-fetch-size: 100 lazy-loading-enabled: true mapper-locations: classpath:mapper/**/*.xml type-aliases-package: com.example.model4.3 插件开发实战
实现分页插件示例:
@Intercepts(@Signature(type= StatementHandler.class, method="prepare", args={Connection.class, Integer.class})) public class PaginationInterceptor implements Interceptor { @Override public Object intercept(Invocation invocation) throws Throwable { StatementHandler handler = (StatementHandler) invocation.getTarget(); BoundSql boundSql = handler.getBoundSql(); // 解析分页参数 PageParam pageParam = getPageParam(boundSql.getParameterObject()); if(pageParam != null) { String originalSql = boundSql.getSql(); String pagedSql = buildPagedSql(originalSql, pageParam); // 通过反射修改SQL Field field = boundSql.getClass().getDeclaredField("sql"); field.setAccessible(true); field.set(boundSql, pagedSql); } return invocation.proceed(); } // 注册到配置类 @Bean public PaginationInterceptor paginationInterceptor() { return new PaginationInterceptor(); } }5. 性能调优与监控方案
5.1 连接池选型对比
| 指标 | HikariCP | Druid | Tomcat JDBC |
|---|---|---|---|
| 获取连接速度 | ⭐⭐⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐ |
| 监控功能 | 基础 | 全面 | 有限 |
| SQL防注入 | 不支持 | 支持 | 不支持 |
| 分布式事务 | 不支持 | 支持 | 不支持 |
5.2 监控集成方案
- Druid监控中心:
@Bean public ServletRegistrationBean<StatViewServlet> druidServlet() { ServletRegistrationBean<StatViewServlet> reg = new ServletRegistrationBean<>(); reg.setServlet(new StatViewServlet()); reg.addUrlMappings("/druid/*"); reg.addInitParameter("loginUsername", "admin"); reg.addInitParameter("loginPassword", "admin"); return reg; }- Prometheus监控指标:
@Bean public CollectorRegistry metricRegistry() { CollectorRegistry registry = new CollectorRegistry(); HikariDataSource dataSource = (HikariDataSource) defaultDataSource(); new HikariCPCollector(dataSource, "app_db").register(registry); return registry; }6. 典型问题排查手册
6.1 常见异常处理
| 异常现象 | 根本原因 | 解决方案 |
|---|---|---|
| Invalid bound statement | Mapper.xml未加载或ID不匹配 | 检查mapper-locations配置 |
| Transaction not active | @Transactional未生效 | 确保@EnableTransactionManagement |
| Too many connections | 连接泄漏 | 使用Druid的removeAbandoned配置 |
| N+1查询问题 | 嵌套查询未优化 | 使用@FetchType.LAZY或批量查询 |
6.2 日志配置技巧
# 显示执行的SQL及参数 logging.level.org.mybatis=DEBUG # 显示事务管理日志 logging.level.org.springframework.jdbc=DEBUG # 显示连接池操作 logging.level.com.zaxxer.hikari=INFO7. 架构演进建议
对于不同规模项目的技术选型建议:
- 小型项目:直接使用Spring Boot Starter + 注解开发模式
- 中大型项目:推荐Spring Boot + MyBatis Plus + 多数据源配置
- 超大规模系统:考虑ShardingSphere分库分表 + 自定义插件体系
未来演进方向:
- 与Spring Data的融合使用
- 响应式编程支持(如R2DBC)
- 云原生适配(Service Mesh集成)