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 的边界细节以官方文档为准。