MyBatis 注解开发
·
本文是介绍如何用注解替代 XML 配置文件,完成 SQL 映射、结果集映射以及二级缓存的配置。
一、为什么要用注解开发
XML 开发需要维护大量 mapper.xml 文件,对于简单的 CRUD 操作略显繁琐。注解开发把 SQL 直接写在接口方法上,减少文件数量,代码更集中。
两种方式对比:
| XML 开发 | 注解开发 | |
|---|---|---|
| SQL 位置 | mapper.xml 文件 | 接口方法上的注解 |
| 结果映射 | <resultMap> | @Results + @Result |
| 注册方式 | resource="mapper/StudentMapper.xml" | class="com.demo.mapper.StudentMapper" |
| 适用场景 | 复杂 SQL、动态 SQL | 简单 CRUD |
二、核心注解说明
| 注解 | 对应 XML 标签 | 作用 |
|---|---|---|
@Select | <select> | 查询 SQL |
@Insert | <insert> | 插入 SQL |
@Update | <update> | 更新 SQL |
@Delete | <delete> | 删除 SQL |
@Results | <resultMap> | 声明结果集映射 |
@Result | <result> | 单个字段映射 |
@ResultMap | resultMap="xxx" | 复用已声明的 resultMap |
@CacheNamespace | <cache/> | 开启二级缓存 |
三、基本用法
XML 写法 vs 注解写法
XML:
<select id="findAll" resultMap="userMap">
select * from user
</select>
<resultMap id="userMap" type="User">
<result property="id" column="id"/>
<result property="username" column="username"/>
<result property="birthday" column="birthday"/>
<result property="sex" column="sex"/>
<result property="address" column="address"/>
</resultMap>
注解:
@Select("select * from user")
@Results(id = "userMap", value = {
@Result(property = "id", column = "id"),
@Result(property = "username", column = "username"),
@Result(property = "birthday", column = "birthday"),
@Result(property = "sex", column = "sex"),
@Result(property = "address", column = "address")
})
List<User> findAll();
什么时候可以省略
@Results?
当 Java 属性名和数据库列名完全一致时,MyBatis 可以自动映射,无需声明。只有字段名不一致时才需要@Results。
复用 ResultMap
@Results 的 id 属性可以给这个映射起名字,在其他方法上通过 @ResultMap 复用:
@Select("select * from user where id = #{id}")
@ResultMap("userMap") // 复用上面声明的 userMap
User findById(int id);
四、完整 CRUD 示例
public interface UserDao {
// 查询所有
@Select("select * from user")
@Results(id = "userMap", value = {
@Result(property = "id", column = "id", id = true),
@Result(property = "username", column = "username"),
@Result(property = "birthday", column = "birthday"),
@Result(property = "sex", column = "sex"),
@Result(property = "address", column = "address")
})
List<User> findAll();
// 根据 id 查询
@Select("select * from user where id = #{id}")
@ResultMap("userMap")
User findById(int id);
// 新增
@Insert("insert into user(username, birthday, sex, address) " +
"values(#{username}, #{birthday}, #{sex}, #{address})")
void insert(User user);
// 修改
@Update("update user set username=#{username}, birthday=#{birthday}, " +
"sex=#{sex}, address=#{address} where id=#{id}")
void update(User user);
// 删除
@Delete("delete from user where id = #{id}")
void delete(int id);
}
五、注解开发中注册 Mapper
注解开发不再有 mapper.xml 文件,sqlMapConfig.xml 中注册方式也要改变:
XML 开发(指向文件):
<mappers>
<mapper resource="mapper/UserMapper.xml"/>
</mappers>
注解开发(指向接口类):
<mappers>
<mapper class="com.qcby.dao.UserDao"/>
<mapper class="com.qcby.dao.StudentDao"/>
<mapper class="com.qcby.dao.TeacherDao"/>
</mappers>
原理:SQL 已经通过注解写在接口里,MyBatis 直接扫描接口类即可找到所有 SQL,不再需要 XML 文件。
六、注解开发中开启二级缓存
XML 开发用 <cache/> 标签,注解开发用 @CacheNamespace:
@CacheNamespace // 对应 XML 里的 <cache/>
public interface UserDao {
// ...
}
带参数的配置:
@CacheNamespace(
eviction = FifoCache.class, // 淘汰策略:先进先出
flushInterval = 60000, // 每 60 秒刷新一次缓存
size = 512, // 最多缓存 512 个对象
readWrite = true // 开启读写缓存(需要序列化)
)
public interface UserDao {
// ...
}
注意:开启二级缓存后,实体类必须实现
Serializable接口,否则运行时会报错。
七、注解开发 vs XML 开发,如何选择
推荐注解开发的场景:
- 简单的单表 CRUD
- SQL 逻辑固定,不需要动态拼接
- 追求代码简洁,减少 XML 文件
推荐 XML 开发的场景:
- 复杂的动态 SQL(
<if>、<foreach>、<choose>等) - SQL 较长,注解里写会影响可读性
- 需要精细的 SQL 调优和维护
实际项目中两种方式可以混用,简单查询用注解,复杂查询用 XML。
总结
@Select/@Insert/@Update/@Delete | 直接在接口方法上写 SQL,替代 XML 标签 |
@Results + @Result | 替代 <resultMap>,处理字段名不一致 |
@ResultMap | 复用已声明的 @Results,避免重复配置 |
| mapper 注册方式 | 注解开发用 class=,XML 开发用 resource= |
@CacheNamespace | 替代 <cache/>,开启接口级别的二级缓存 |
更多推荐



所有评论(0)