# MyBatis教程 - 9 使用注解开发
MyBatis 提供了注解开发的方式,可以让开发者不依赖 XxxMapper.xml
配置文件,直接在 XxxMapper.java
接口上使用注解来编写 SQL 语句。
但是对于复杂的 SQL 语句,使用注解的方式不易处理,所以针对简单的 SQL,可以使用注解的开发方式,而对于复杂的 SQL 还是建议使用 XxxMapper.xml
的 SQL 映射文件来完成。
# 9.1 注解方式实现增删改查
下面使用注解的开发方式,实现 User 表的增删改查,对于简单的 SQL,使用注解的方式还是非常方便的。
# 1 定义Mapper接口
还是在 UserMapper.java 中定义增删改查的相关接口,并在接口上使用注解定义 SQL 语句。
UserMapper.java :
package com.foooor.mybatis.mapper;
import com.foooor.mybatis.pojo.User;
import org.apache.ibatis.annotations.*;
public interface UserMapper {
/**
* 根据id查询用户信息
*/
@Select("SELECT * FROM tb_user WHERE id = #{id}")
User selectById(@Param("id") int id);
/**
* 插入用户信息
*/
@Insert("INSERT INTO tb_user(username, password, email, age, create_time, update_time) VALUES (#{username}, #{password}, #{email}, #{age}, #{createTime}, #{updateTime})")
@Options(useGeneratedKeys = true, keyProperty = "id")
int insert(User user);
/**
* 更新用户信息
*/
@Update("UPDATE tb_user SET username = #{username}, password = #{password}, email = #{email}, age = #{age}, update_time = #{updateTime} WHERE id = #{id}")
int update(User user);
/**
* 根据id删除用户信息
*/
@Delete("DELETE FROM tb_user WHERE id = #{id}")
int deleteById(@Param("id") int id);
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
不用使用 UserMapper.xml
映射文件了,直接就可以测试了。
当然,我们可以同时使用注解和 XxxMapper.xml 进行混合开发,但是不能给一个接口同时添加注解和在 XxxMapper.xml 文件中进行 SQL 映射,会报错!
# 2 使用注解开发的优缺点
- 优点:
- 简洁:使用注解避免了冗长的 XML 配置,直接将 SQL 语句放在接口上,代码更加简洁。
- 易维护:SQL 语句和代码在一起,便于查看和修改。
- 缺点:
- 复杂 SQL 不易处理:当 SQL 语句变得非常复杂时,注解会显得力不从心。此时,还是需要回到 XML 配置中编写复杂的 SQL 语句。
- 可读性:对于非常长的 SQL 语句,直接写在注解中会导致代码可读性下降。
# 9.2 @Results和@Result注解
当查询数据库的字段名称和 Java 实体类中的属性名称不对应的时候,可以使用 @Results
和 @Result
注解。
@Results
注解是用来定义一组 @Result
的容器,用于指定 SQL 查询结果与实体类属性的映射规则。
举个栗子:
当数据库的字段是 email
,Java 实体类中的属性名称为 mailBox
时,可以使用下面的方式进行映射。
/**
* 根据id查询用户信息
*/
@Select("SELECT * FROM tb_user WHERE id = #{id}")
@Results({
@Result(property = "id", column = "id", id = true),
@Result(property = "username", column = "username"), // 这个可以省略,自动映射
@Result(property = "mailBox", column = "email")
})
User selectById(@Param("id") int id);
2
3
4
5
6
7
8
9
10
在处理的时候,当名称不匹配的时候,使用 @Result
进行映射,如果名称是匹配的,MyBatis 会自动处理映射,无需使用 @Result
注解。所以上面的 username
是可以省略的。id
建议添加,标识主键。
还可以进行级联映射:
/**
* 根据id查询学生信息
*/
@Select("SELECT stu.id as sid, stu.name as sname, stu.age, cla.id as cid, cla.name as cname, cla.student_count " +
"FROM tb_student as stu LEFT JOIN tb_cla55 as cla ON stu.cla55_id = cla.id " +
"WHERE stu.id = #{id}")
@Results({
@Result(property = "id", column = "sid", id = true),
@Result(property = "name", column = "sname"),
@Result(property = "age", column = "age"),
@Result(property = "cla55.id", column = "cid"),
@Result(property = "cla55.name", column = "cname"),
@Result(property = "cla55.studentCount", column = "student_count")
})
Student selectStuAndClassById(@Param("id") Integer id);
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 9.3 多对一和一对多映射
使用注解也可以进行多对一和一对多的关系映射。
# 1 多对一映射
@Result
注解中有 one
属性,使用 one
属性可以进行多对一的关系映射。
举个栗子:
StudentMapper.java
:
/**
* 根据id查询学生信息
*/
@Select("SELECT * FROM tb_student WHERE id = #{id}")
@Results({
@Result(property = "id", column = "id", id = true),
@Result(property = "name", column = "name"), // 名称匹配,可以省略
@Result(property = "cla55", column = "cla55_id", one = @One(select = "com.foooor.mybatis.mapper.Cla55Mapper.selectById", fetchType = FetchType.EAGER))
})
Student selectStuAndClassById(@Param("id") Integer id);
2
3
4
5
6
7
8
9
10
映射的时候,指定映射的属性和数据库字段,并指定查询关联的对象属性的 Mapper 方法。
# 2 一对多映射
@Result
注解中有 many
属性,使用 many
属性可以进行一对多的关系映射。
举个栗子:
Cla55Mapper.java
:
/**
* 根据id查询班级和学生信息
*/
@Select("SELECT * FROM tb_cla55 WHERE id = #{id}")
@Results({
@Result(column = "id", property = "id", id = true),
@Result(column = "name", property = "name"),
@Result(column = "studentCount", property = "studentCount"),
@Result(column = "id", property = "studentList", many = @Many(select = "com.foooor.mybatis.mapper.StudentMapper.selectByCla55Id", fetchType = FetchType.EAGER))
})
Cla55 selectClassAndStuById(@Param("id") Integer id);
2
3
4
5
6
7
8
9
10
11
← 08-多对一和一对多 10-动态SQL →