mybatis-spring 浅析

mybatis-springMyBatis 官方团队 开发的一个桥接模块,其核心目标是:让 MyBatis 能够无缝集成到 Spring Framework 应用中,充分利用 Spring 的依赖注入(DI)、事务管理、生命周期管理等能力。


一、mybatis-spring 是谁开发的?

  • 开发者:MyBatis 官方团队(原 iBATIS 团队演进而来)

  • GitHub 仓库https://github.com/mybatis/spring

  • Maven 坐标

    复制代码
    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis-spring</artifactId>
      <version>3.0.3</version> <!-- 最新版本请查 Maven Central -->
    </dependency>

💡 虽然由 MyBatis 社区维护,但它被广泛认可为 Spring 生态中集成 MyBatis 的标准方式 ,也被 Spring Boot 官方 starter(mybatis-spring-boot-starter)所依赖。


二、mybatis-spring 主要做了什么?

它解决了 "如何让非 Spring 原生框架(MyBatis)在 Spring 容器中正确运行" 的问题。具体来说,它完成了以下关键工作:


1. SqlSessionFactory 纳入 Spring 容器管理

MyBatis 的核心是 SqlSessionFactory,但它是 MyBatis 自己的对象,不是 Spring Bean。

mybatis-spring 提供了:

复制代码
org.mybatis.spring.SqlSessionFactoryBean

这是一个 Spring 的 FactoryBean<SqlSessionFactory> ,允许你在 Spring 配置中像声明普通 Bean 一样创建 SqlSessionFactory

复制代码
@Bean
public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
    SqlSessionFactoryBean factory = new SqlSessionFactoryBean();
    factory.setDataSource(dataSource);
    return factory.getObject(); // 返回真正的 SqlSessionFactory
}

这样,SqlSessionFactory 就成了 Spring 容器的一部分,可以被其他 Bean 注入或引用。


2. 自动为 Mapper 接口生成代理实现(并注册为 Spring Bean)

在纯 MyBatis 中,你需要手动调用:

复制代码
UserMapper mapper = sqlSession.getMapper(UserMapper.class);

但在 Spring 中,我们希望直接 @Autowired 使用:

复制代码
@Service
public class UserService {
    @Autowired
    private UserMapper userMapper; // 直接注入!
}

mybatis-spring 通过以下机制实现这一点:

(1)MapperFactoryBean
  • 单个 Mapper 接口创建代理对象,并注册为 Spring Bean。

  • 示例(XML 配置时代常用):

    复制代码
    <bean id="userMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
      <property name="mapperInterface" value="com.example.UserMapper"/>
      <property name="sqlSessionFactory" ref="sqlSessionFactory"/>
    </bean>
(2)MapperScannerConfigurer(XML)或 @MapperScan(Java Config)
  • 自动扫描包下所有接口,批量注册为 Spring Bean。

  • 这就是你在 Spring Boot 中常用的:

    复制代码
    @MapperScan("com.example.demo.mapper")
    @Configuration
    public class MyBatisConfig { ... }
  • 底层原理:利用 Spring 的 BeanDefinitionRegistryPostProcessor,在容器启动时动态注册 MapperFactoryBean 的定义。

✅ 最终效果:每个 Mapper 接口都对应一个 Spring Bean,可以直接注入使用。


3. 与 Spring 事务管理无缝集成

MyBatis 本身有自己的事务控制(SqlSession.commit() / rollback()),但这和 Spring 的声明式事务(@Transactional)冲突。

mybatis-spring 提供了:

复制代码
org.mybatis.spring.SqlSessionTemplate
  • 这是一个 线程安全的、Spring 事务感知的 SqlSession 代理
  • 它会自动加入 Spring 的事务上下文:
    • 如果当前有 Spring 事务,则复用同一个数据库连接
    • 如果没有,则开启新连接并在方法结束时自动关闭

同时,你通常不需要直接使用 SqlSessionTemplate,因为 Mapper 代理内部已经使用它了。

🔄 效果:在 @Transactional 方法中调用多个 Mapper,它们共享同一个数据库连接和事务!


4. 异常转换(Exception Translation)

MyBatis 抛出的是 PersistenceException 等,而 Spring 推荐使用统一的 DataAccessException 层级。

mybatis-spring 自动将 MyBatis 异常转换为 Spring 的 DataAccessException 子类(如 DuplicateKeyException),便于统一处理。


三、架构图简示

复制代码
+---------------------+
|   Spring Container  |
+----------+----------+
           |
           | 注入
+----------v----------+
|   UserMapper (Proxy)|
+----------+----------+
           | 调用
+----------v----------+
| SqlSessionTemplate  | ←--- 绑定到 Spring 事务
+----------+----------+
           |
+----------v----------+
| SqlSessionFactory   |
+----------+----------+
           |
+----------v----------+
|     DataSource      |
+---------------------+

四、总结:mybatis-spring 的核心价值

功能 解决的问题
SqlSessionFactoryBean SqlSessionFactory 成为 Spring Bean
@MapperScan / MapperFactoryBean 自动将 Mapper 接口注册为可注入的 Spring Bean
SqlSessionTemplate 使 MyBatis 会话参与 Spring 事务管理
异常转换 统一数据访问异常体系
生命周期管理 由 Spring 控制资源创建与销毁

一句话总结
mybatis-spring 是 MyBatis 与 Spring 之间的"翻译官"和"粘合剂",让 MyBatis 能像原生 Spring 组件一样被管理和使用。


如果你使用 Spring Boot + MyBatis,底层正是通过 mybatis-spring 实现的集成。理解它,就理解了 MyBatis 在 Spring 中工作的本质。

相关推荐
梅梅绵绵冰2 小时前
springmvc文件上传
java·开发语言
龙华2 小时前
Maven多仓库/依赖配置
java·maven
天道佩恩2 小时前
MapStruct转换实体
java·后端
Boop_wu2 小时前
[Java 面试] 多线程1
java·开发语言
专注于大数据技术栈2 小时前
java学习--main方法
java·开发语言·学习
2501_941802482 小时前
C++高性能并发编程实战:从多线程管理到内存优化与任务调度全流程解析
java·开发语言·c++
0***R5152 小时前
SpringBoot集成Elasticsearch实战
java·spring boot·elasticsearch
爱学java的ptt2 小时前
ThreadLocal细节
java