MyBatis注解版详解
MyBatis之注解版 Java 1.5起,随着注解的流行,Mybatis也与时俱进地推出了基于注解的新版本。
1 注解版基本使用
pom依赖和yml配置文件以及相关数据见前文:SpringBoot系列(八):MyBatis之XML 配置版。 注解版与xml配置版的不同在于,注解版不再需要配置xml文件,直接在dao层接口中通过注解书写sql语句即可。
1.1 @Select 注解
@Select 主要在查询的时候使用,具体如下:
@Select("SELECT * FROM users")
List<User> getUserList();
1.2 @Insert 注解
插入数据库时使用:
@Insert("INSERT INTO users(userName,passWord,user_sex) VALUES(‘xiaohong’, ‘123456‘, ‘male’)")
void addUser();
1.3 @Update 注解
所有的更新操作 SQL 都可以使用 @Update:
@Update("UPDATE users SET userName='xiaohong2',password=#{passWord} WHERE id = 1")
void updateUser();
1.4 @Delete 注解
处理数据删除:
@Delete("DELETE FROM users WHERE id =1")
void deleteUser();
2 参数传递
上面的例子演示了基本的增删改查语句,但在实际项目中,肯定不能将参数写成具体的值,这就涉及到如何参数传递的问题了。 如果参数只有一个,直接在方法中使用参数,并在SQL中使用#{sex}来接收同名参数。更多教程请访问码农之家
@Select("SELECT * FROM users WHERE sex = #{sex}")
List<User> getUserList(String sex);
如果有多个参数时,就需要用@Param标签来进行映射了。
2.1 @Param 注解传参
@Select("SELECT * FROM users WHERE sex = #{sex} AND age > #{age}")
List<User> getUsersBySex(@Param("sex") String sex,@Param("age") int age);
2.2 Map传参
当参数很多时,可以考虑使用Map传参:
@Select("SELECT * FROM users WHERE user_name=#{userName} AND user_sex = #{sex}")
List<User> getUsersByNameAndSex(Map<String, Object> map);
在调用该方法时,将参数依次加入map中:
Map param = new HashMap();
param.put("userName","xiaohong");
param.put("sex","male");
List<User> users = userMapper.getListByNameAndSex(param);
2.3 对象传参
Insert("INSERT INTO users(userName,passWord,sex) VALUES(#{userName}, #{passWord}, #{sex})")
void addUser(User user);
在执行时,系统会自动读取对象的属性并值赋值到同名的 #{xxx} 中。
2.4 # 符号和$ 符号的区别
@Select("SELECT * FROM user WHERE user_name = #{userName}")
User getUserByName(@Param("userName") String userName);
@Select("SELECT * FROM user WHERE user_name = '${userName}'")
User getUserByName(@Param("userName") String userName);
通过这个例子,可以看出 # 会对SQL进行预处理,使用 $ 时会直接将值拼接到SQL中。使用 $ 有SQL注入的风险,但当库表名需要进行参数化时适合使用 $。
3 字段映射
实际项目中,经常出现Mysql命名规范与Java的差异性导致的数据库字段名与Java实体类变量名不一致的情况。这个在前文中,已经讲述了解决方案。那么在注解版如何解决这个问题呢?Mybatis提供了两个注解:@Results 和 @Result 注解,这两个注解配合来使用,主要作用是将数据库中查询到的数值转化为具体的字段,修饰返回的结果集,关联实体类属性和数据库字段一一对应,如果实体类属性和数据库属性名保持一致,就不需要这个属性来修饰。示例如下:
@Select("SELECT * FROM users")
@Results({
@Result(property = "sex", column = "sex", javaType = UserSexEnum.class),
@Result(property = "userName", column = "user_name")
})
List<User> getUserList();
4 动态SQL
MyBatis 可以灵活的支持动态 SQL,在前文xml配置版中已有详细阐述,与之对应的,在注解版中Mybatis提供了两种方式来支持,第一种是使用注解来实现,另一种是提供 SQL 类来支持。
4.1 使用注解实现
用 script 标签包围,然后像 XML 语法一样书写:
@Update("<script>
update users
<set>
<if test="userName != null">user_name=#{userName},</if>
<if test="sex!= null">sex=#{sex},</if>
</set>
where id=#{id}
</script>")
void update(User user);
这种方式就是注解 + XML 的混合使用方式,既有 XML 灵活又有注解的方便,但也有一个缺点需要在 Java 代码中拼接 XML 语法很不方便,因此 MyBatis 又提供了一种更优雅的使用方式来支持动态构建 SQL。
4.2 使用 SQL 构建类
可以看出 UserSql 中有一个方法 getList,使用 StringBuffer 对 SQL 进行拼接,通过 if 判断来动态构建 SQL,最后方法返回需要执行的 SQL 语句。
public class UserSql {
public String getUserList(User user) {
StringBuffer sql = new StringBuffer("select id, user_name, password, sex, nick_name as nickName");
sql.append(" from users where 1=1 ");
if (userParam != null) {
if (StringUtils.isNotBlank(user.getUserName())) {
sql.append(" and user_name = #{userName}");
}
if (StringUtils.isNotBlank(user.getSex())) {
sql.append(" and sex = #{sex}");
}
}
sql.append(" order by id desc");
sql.append(" limit " + user.getBeginLine() + "," + user.getPageSize());
log.info("getList sql is :" +sql.toString());
return sql.toString();
}
}
接下来只需要在 Mapper 中引入这个类和方法即可。
@SelectProvider(type = UserSql.class, method = "getUserList")
List<UserEntity> getList(User user);
两个参数:
- type:动态生成 SQL 的类
- method:类中具体的方法名
4.3 结构化 SQL
public String getCount(UserParam userParam) {
String sql= new SQL(){{
SELECT("count(1)");
FROM("users");
if (StringUtils.isNotBlank(userParam.getUserName())) {
WHERE("userName = #{userName}");
}
if (StringUtils.isNotBlank(userParam.getUserSex())) {
WHERE("user_sex = #{userSex}");
}
//从这个 toString 可以看出,其内部使用高效的 StringBuilder 实现 SQL 拼接
}}.toString();
log.info("getCount sql is :" +sql);
return sql;
}
- SELECT 表示要查询的字段,可以写多行,多行的 SELECT 会智能地进行合并而不会重复。
- FROM 和 WHERE 跟 SELECT 一样,可以写多个参数,也可以在多行重复使用,最终会智能合并而不会报错。这样语句适用于写很长的 SQL,且能够保证 SQL 结构清楚,便于维护、可读性高。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
· 三行代码完成国际化适配,妙~啊~