MyBatisPlus自定义sql
MyBatisPlus自定义sql
在说怎么实现之前我们要先明白一个概念,就是mybatis-plus是在mybatis的基础上进行增强,并不做改变,所以mybatis的操作在mybatis-plus中也是一样可以使用的,咱们直接上代码.
1、单纯地使用注解自定义SQL
数据库数据:
执行测试方法后结果如下:
注意:这里我们把MybatisPlusConfig这个类注释掉,持久层的类使用@Mapper注解,也是一样可以运行的哈。
结果:
2、使用注解加标签做自定义sql
展示1:使用if标签
结果:
展示2:使用foreach标签
结果:
展示3:使用foreach标签
下面我们使用id来查找一下:
结果:
扩展知识点:{} 和 ${} 的区别?
一、区别概述
1.1、主要区别:
1、#{} 是预编译处理,${} 是直接替换;
2、${} 存在SQL注入的问题,而 #{} 不存在;
Ps:这也是面试主要考察的部分~
1.2、细节上:
1、${} 可以实现排序查询,#{} 不能实现排序查询。
2、${} 可以直接进行模糊查询(但不建议,存在 SQL 注入问题),#{} 不可以直接进行模糊查询,但可以通过 mysql 内置函数 concat() 实现模糊查询(不存在 SQL 注入问题)。
二、具体描述
2.1、预编辑处理 vs 直接替换
预编辑处理:是指 MyBatis 在处理 #{} 时,就是把 #{} 替换成了 ?号,使用 PreparedStatement 的 set 方法来赋值。也就是说 #{} 会把 {} 内的整体看成 value ,最后再给 value 加上单引号,重点强调引号内部是一个整体( #{} 不会发生 SQL 注入的根本原因)。
直接替换:是指 MyBatis 在处理 ${} 时,会把 ${} 替换成变量的值(不会加引号处理)。
2.2、SQL 注入问题
2.2.1、引发 SQL 注入
例如现在有一个登陆程序,需要输入正确的账户和密码才能登录,当使用了 SQL 注入就可以在不知道密码的情况下进行登录,如下
xml 文件如下:
select * from userinfo where username = '${username}' and password = '${password}'
接口如下:
/** * 登录逻辑 * @param username * @param password * @return */ Userinfo login(@Param("username") String username, @Param("password") String password);
测试方法如下:
@Test void login() { String username = "admin"; String password = "' or 1 = '1"; Userinfo userinfo = userMapper.login(username, password); System.out.println("登录状态:" + (userinfo == null ? "失败" : "成功")); }
执行结果如下:
2.2.2、SQL 注入分析
可以在运行结果的日志中看到,我们最后执行的SQL语句如下:
在 MySQL 中 1 = ‘1’ 结果必然为 true,所以不难分析出,如上 SQL 一定会将这张表中的用户全部返回(即使账号都填写错了,照样返回,因为1 = ‘1’ 必然为 true );
使用 ${} 的注意事项:一定是可以穷举的值,在使用之前一定要对传递的值进行合法性验证(在Controller中通过穷举的方式验证安全性)。
2.3、排序查询
使用 ${} 可以实现排序查询,而 #{} 不可以实现排序查询,因为使用 #{} 查询时,如果传递的值为 String 就会加单引号,导致 sql 错误。
例如你期望的 sql 语句为:select * from userinfo order by id desc;
而 #{sort} 中传入的是一个 String 类型的值为 “desc”;
那么最终实际的 sql 语句为:select * from userinfo order by id ‘desc’;这必然是错误的~
2.4、like 查询
2.4.1、${} 模糊查询
方式一:直接替换 select * from userinfo where username like '%${key}%' 方式二:使用concat进行字符串拼接 select * from userinfo where username like concat('%', '${key}', '%')
Ps:虽然可以这样,但并不建议使用 ${} 进行模糊查询,因为存在 SQL 注入问题。
2.4.2、#{} 模糊查询
select * from userinfo where username like concat('%', #{key}, '%')
2.4.3、#{} 模糊查询问题分析
你期望的 sql 语句:select * from user where username = ‘%abc%’;
然而当你使用 #{} 传入的参数会自带引号,于是就变成了:select * from user where username = ‘%’ abc ‘%’;
注意:
注意一点:接口里面的形参如果没有使用@Param注解,那么你sql里面就不能直接用${}

1)使用@Param注解 当以下面的方式进行写SQL语句时: @Select("select column from table where userid = #{userid} ")