数据访问(三):MyBatis
starter 与版本注意
MyBatis 由第三方社区维护,与 Spring Boot 的集成 starter 为 mybatis-spring-boot-starter(组 ID org.mybatis.spring.boot)。引入时务必选择与所用 Boot 主线兼容的版本:Boot 3.x 对应 3.x 版本线,Boot 4.x 需用更新的主版本,具体以 MyBatis 官方发布说明为准:
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>(与 Boot 主线匹配的版本)</version>
</dependency>
还需要数据库驱动(同 14 章)。启动类加 @MapperScan("com.example.demo.mapper"),或在每个 Mapper 接口上加 @Mapper(二选一),MyBatis 会自动创建 SqlSessionFactory 并扫描 Mapper。
注解方式
适合简单 SQL:
@Mapper
public interface UserMapper {
@Select("select * from t_user where id = #{id}")
User findById(Long id);
@Insert("insert into t_user(name, age) values (#{name}, #{age})")
@Options(useGeneratedKeys = true, keyProperty = "id")
int insert(User user);
@Update("update t_user set age = #{age} where id = #{id}")
int updateAge(@Param("id") Long id, @Param("age") int age);
@Delete("delete from t_user where id = #{id}")
int deleteById(Long id);
}
要点:#{...} 是预编译占位符(防 SQL 注入);多个参数必须用 @Param 命名,或用对象传参;@Options(useGeneratedKeys = true) 可取回自增主键并回填到对象。
XML 方式
复杂 SQL 推荐 XML。Mapper 接口只写方法签名:
public interface UserMapper {
List<User> search(@Param("name") String name, @Param("minAge") Integer minAge);
}
XML 放 src/main/resources/mapper/UserMapper.xml,namespace 等于接口全限定名、id 等于方法名:
<mapper namespace="com.example.demo.mapper.UserMapper">
<select id="search" resultType="com.example.demo.entity.User">
select * from t_user
<where>
<if test="name != null and name != ''">
and name like concat('%', #{name}, '%')
</if>
<if test="minAge != null">
and age >= #{minAge}
</if>
</where>
</select>
</mapper>
配置 XML 位置与驼峰映射:
mybatis.mapper-locations=classpath:mapper/*.xml
mybatis.configuration.map-underscore-to-camel-case=true
map-underscore-to-camel-case 开启后,t_user 表的 user_name 列可自动映射到 userName 字段。动态 SQL 的 <where>/<if>/<foreach> 是 MyBatis 处理多变查询条件的主要手段。同一方法不能同时用注解和 XML 定义,否则启动报错。
与 Spring Data JPA 的选择
| 维度 | Spring Data JPA | MyBatis |
|---|---|---|
| 编程模型 | 实体驱动,接口即实现 | SQL 驱动,SQL 完全在手 |
| 简单 CRUD | 零代码 | 每个方法都要写 |
| 复杂查询/报表 SQL | 需 JPQL/原生 SQL 打磨 | 直接写原生 SQL + 动态 SQL |
没有绝对优劣:追求开发效率与对象化建模选 JPA,追求 SQL 可控、团队普遍熟悉 SQL 时选 MyBatis。
小结
MyBatis 的集成三步:引入匹配版本的 starter → 扫描 Mapper 接口 → 用注解或 XML 写 SQL。注解适合小 SQL,XML + 动态 SQL 是复杂查询的主力,配合 map-underscore-to-camel-case 可省去大量手工映射。