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 方案见下一章。

笔记加载中…