MyBatis 与 Spring 集成
原生方式要自己开 SqlSession、管事务,代码里到处是样板。接入 Spring 后,SqlSession 的创建与关闭、事务边界、Mapper 实现统统交给容器,业务代码只需注入 Mapper 接口直接调用——这靠官方整合项目 mybatis-spring 完成。
为什么要集成
- 生命周期托管:SqlSessionFactory 作为单例 Bean 交给 Spring,SqlSession 由框架按需创建/关闭。
- Mapper 零实现:接口被扫描后自动生成代理 Bean,直接 @Autowired 注入。
- 事务统一:SqlSession 自动加入 Spring 事务(@Transactional),提交回滚与 Spring 一致。
- 异常翻译:MyBatis 异常自动转成 Spring 的 DataAccessException。
添加依赖
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>3.x</version> <!-- Spring 6 用 3.x;Spring 5 用 2.x -->
</dependency>
mybatis-spring 与 Spring、MyBatis 主版本有对应关系表,集成前先查官方文档确认。
三个核心组件
① SqlSessionFactoryBean——替代手动 SqlSessionFactoryBuilder,把数据源、全局配置、映射文件组装成 SqlSessionFactory:
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="configLocation" value="classpath:mybatis-config.xml"/>
<property name="mapperLocations" value="classpath:mapper/*.xml"/>
<property name="typeAliasesPackage" value="com.example.entity"/>
<!-- 自定义插件(Interceptor[])等属性可选 -->
</bean>
② MapperScannerConfigurer——扫描指定包下的 Mapper 接口,批量注册成 Bean:
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.example.mapper"/>
</bean>
注解配置更简单:在 @Configuration 类上加 @MapperScan("com.example.mapper")(org.mybatis.spring.annotation.MapperScan),等价于上面的扫描器。
③ SqlSessionTemplate——扫描器生成的 Mapper 代理内部用它执行 SQL。它是线程安全的,自动开/关 SqlSession、把执行纳入当前 Spring 事务。
完整 XML 装配示例
<bean id="dataSource" class="com.zaxxer.hikari.HikariDataSource">
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/demo"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</bean>
<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.mapper"/>
</bean>
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
业务层直接注入使用:
@Service
public class UserService {
private final UserMapper userMapper;
public UserService(UserMapper userMapper) {
this.userMapper = userMapper;
}
@Transactional
public void createWithTx(User user) {
userMapper.insert(user);
// 抛异常时整个事务回滚
}
}
行为要点
- 事务内共享 SqlSession:一个 Spring 事务全程共用一个 SqlSession,一级缓存随事务存活;无事务时每次 Mapper 调用都是独立 SqlSession(第 10 章的影响在这里体现)。
- 事务边界用 @Transactional 控制,不要再手动 session.commit()。
- mapperLocations 未命中会报 Invalid bound statement,路径要写对、XML 需在 classpath 内。
小结
集成三件套:SqlSessionFactoryBean 建工厂、MapperScannerConfigurer(或 @MapperScan)扫接口、SqlSessionTemplate 跑 SQL,事务交给 @Transactional。版本匹配与完整属性以 mybatis-spring 官方文档为准;Spring Boot 场景的 starter 方案见下一章。