MyBatis 注解开发

除了 Mapper XML,MyBatis 还支持用注解在 Mapper 接口上直接写 SQL。简单 SQL 用注解可以少建一个 XML 文件;动态 SQL、复杂映射仍然是 XML 的主场。常见工程做法是:简单语句注解、复杂语句 XML,两者共存。

一个注解版 Mapper

import org.apache.ibatis.annotations.*;

public interface UserMapper {
    @Select("SELECT id, name, age FROM user WHERE id = #{id}")
    User selectById(Integer id);

    @Select("SELECT id, name, age FROM user")
    List<User> selectAll();

    @Insert("INSERT INTO user(name, age) VALUES(#{name}, #{age})")
    int insert(User user);

    @Update("UPDATE user SET name = #{name}, age = #{age} WHERE id = #{id}")
    int update(User user);

    @Delete("DELETE FROM user WHERE id = #{id}")
    int delete(Integer id);
}

@Select/@Insert/@Update/@Delete 一一对应四类语句;增删改返回受影响行数 int。接口需要注册进配置(<mappers><package name="com.example.mapper"/></mappers>),再用 SqlSession.getMapper 或 Spring 的 @MapperScan 使用。

主键回填:@Options

注解版回填自增主键,等价于 XML 的 useGeneratedKeys:

@Insert("INSERT INTO user(name, age) VALUES(#{name}, #{age})")
@Options(useGeneratedKeys = true, keyProperty = "id")
int insert(User user);

执行后 user.getId() 就能拿到数据库生成的主键。

多参数:@Param

多个参数要命名,规则与 XML 完全一致:

@Select("SELECT id, name, age FROM user WHERE name = #{name} AND age = #{age}")
User selectByNameAndAge(@Param("name") String name, @Param("age") Integer age);

单对象参数直接写属性名:#{name} 取自 user.getName()。

结果映射:@Results / @Result

列名与属性对不上时用 @Results 声明(等价于 XML 的小 resultMap):

@Select("SELECT id, user_name, age FROM user WHERE id = #{id}")
@Results(id = "userMap", value = {
        @Result(id = true, property = "id", column = "id"),
        @Result(property = "name", column = "user_name")
})
User selectById(Integer id);

@Result(id=true) 对应 XML 的 <id>;id 属性给这组映射起名后,可在其他方法上复用:

@Select("SELECT id, user_name, age FROM user")
@ResultMap("userMap")   // 也可引用 XML resultMap 的 id
List<User> selectAll();

动态 SQL:Provider 与 <script>

注解里写的是静态 SQL 文本,没有 <if><foreach> 可用。需要动态拼接时:一种写法是把 XML 动态标签塞进注解的 <script> 字符串(以官方文档为准);更推荐用 Provider 类,把拼 SQL 的逻辑收敛到 Java 方法里:

public class UserSqlProvider {
    public String selectByName(String name) {
        // 普通 Java 逻辑动态拼 SQL,参数仍用 #{} 占位
        return "SELECT id, name, age FROM user WHERE name = #{name}";
    }
}

public interface UserMapper {
    @SelectProvider(type = UserSqlProvider.class, method = "selectByName")
    User selectByName(String name);
}

Provider 家族还有 @InsertProvider、@UpdateProvider、@DeleteProvider。

注解 vs XML:怎么选

对比项注解XML
简单 SQL推荐,少一个文件可用
动态 SQL(if/foreach)需 Provider/script天然支持
复杂 resultMap 与复用繁琐推荐
SQL 集中管理(DBA 审阅)散落在接口集中在 XML

小结

@Select/@Insert/@Update/@Delete 写静态 SQL,@Options 回填主键、@Param 命名多参数、@Results/@ResultMap 做映射;动态与复杂场景交给 Provider 或 XML。注解与 XML 的边界细节以官方文档为准。

笔记加载中…