【Mybatis-1】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 结构清楚,便于维护、可读性高。
- java教程
- Java快速入门
- Java 开发环境配置
- Java基本语法
- Java 对象和类
- Java 基本数据类型
- Java 变量类型
- Java 修饰符
- Java 运算符
- Java 循环结构
- Java 分支结构
- Java Number类
- Java Character类
- Java String类
- Java StringBuffer和StringBuilder类
- Java 数组
- Java 日期时间
- Java 正则表达式
- Java 方法
- Java 流(Stream)、文件(File)和IO
- Java 异常处理
- Java 继承
- Java 重写(Override)与重载(Overload)
- Java 多态
- Java 抽象类
- Java 封装
- Java 接口
- Java 包(package)
- Java 数据结构
- Java 集合框架
- Java 泛型
- Java 序列化
- Java 网络编程
- Java 发送邮件
- Java 多线程编程
- Java Applet基础
- Java 文档注释
- Android网络技术HttpURLConnection详解
- Ubuntu16.04下CUDA8.0和CUDA9.0共存
- Ubuntu 20.04 开启隐藏录音降噪功能(推荐)
- 解密 Linux 版本信息的方法
- ubuntu20.04连接wifi的方法(2种)
- 服务器Centos部署MySql并连接Navicat过程详解
- Android横竖屏幕切换生命周期详解
- LINUX中如何查看某个端口是否被占用的方法
- Android实现RecyclerView添加分割线的简便方法
- Android定时器Timer的停止和重启实现代码
- Ubuntu20.04开启root账户的方法步骤
- Android 将view 转换为Bitmap出现空指针问题解决办法
- Android ScrollView 下嵌套 ListView 或 GridView出现问题解决办法
- Ubuntu 安装cuda10.1驱动的实现步骤
- Android单例模式的几种方法总结