目录
回顾:
参数占位符#{}和${}
${}唯一使用地方
使用${}造成的SQL注入漏洞
like查询
mapper中接收结果的参数
resultType和resultMap编辑
多表查询
回顾:
参数占位符#{}和${}
- `#{}` 占位符语法通常用于模板引擎或动态查询语句中。它是一种更加安全的占位符,被设计用来防止SQL注入攻击。在大多数情况下,`#{}` 会把传递给它的值作为参数进行处理,并进行适当的转义(预处理)。(加' ')
例如,在使用数据库框架时,可以将查询参数通过 `#{}` 进行占位,如 `SELECT * FROM table WHERE id = #{param}`。这样可以有效地防止 SQL 注入攻击。
- 2. `${}` 占位符语法通常用于配置文件或属性文件中的占位符直接替换。存在SQL注入的问题。
- 其实 '${}' 和 #{}等价
那我们神魔时候使用${}?
/** 参数占位符 #{} 和 ${} :* #{}:预编译处理;* ${}: 字符直接替换;** Mybatis在处理#{}时,会把SQL中的#{}替换成?,使用PaeparedStatement的set方法来复制,直接替换:Mybatis在处理${},是把${}替换成变量的值;* $的应用场景:使用Java中的关键字的时候!* ${sort}可以实现排序查询,而是用#{sort}就不能实现排序查询了,因为当使用#{sort}查询的时候,如果查询的值是String,则会加单引号,就会导致sql错误;** **/
${}唯一使用地方
现在我们要进行升序/降序查询表中信息,
//mapper中的接口import com.example.demo1014.entity.UserInfo; import lombok.Data; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; import java.util.*; @Mapper public interface UserMapper {List<UserInfo> getListByOrder(@Param("order") String order);}
配置xml——因为我们想有那种查询就用那种查询so,order by id${order}
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mapper namespace="com.example.demo1014.mapper.UserMapper"><select id="getListByOrder" resultType="com.example.demo1014.entity.UserInfo">select* from userinfo order by id ${order}</select></mapper> <!--namsespace是xml实现接口的全路径(包名+接口名) id是实现的方法名 resultType是返回的类型 ${}是标签,用来传递参数-->
此时在UserMapper接口中右键generate,选择test,我们就可以
接下来进行SpringBoot单元测试,在Test包中
想要查看日志信息:在application.yml文件中配置
spring:datasource:url: jdbc:mysql://localhost:3306/java2023?characterEncoding=utf8&useSSL=false # MySQL数据库的URL,根据实际情况修改username: rootpassword: 123456driver-class-name: com.mysql.cj.jdbc.Driver # MySQL的JDBC驱动类名,根据实际情况修改mybatis:mapper-locations: classpath:mybatis/*Mapper.xml # 开启mybatis sql 日志打印;configuration:log-impl: org.apache.ibatis.logging.stdout.StdOutImpl# 配置打印MyBatis执行的sql; logging:level:com:example:demo1014: debug
点击运行就可以看到排序好了
但是当我们把${}改成#{},就不行了,会给asc/desc加上单引号。
使用${}造成的SQL注入漏洞
当我们在用姓名和邮箱号作为查询用户信息的时候,有一个不对我们都不能让他查询到,
前面我们说了'${}'等价于#{},当我们在mapper中的接口进行.xml(resourse包下的)配置时如果使用
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mapper namespace="com.example.demo1014.mapper.UserMapper"><select id="login" resultType="com.example.demo1014.entity.UserInfo">select* from userinfo where name='${name}' and email =#{email}</select> </mapper> <!--namsespace是xml实现接口的全路径(包名+接口名) id是实现的方法名 resultType是返回的类型 ${}是标签,用来传递参数-->
回到mapper中的接口:进行单元测试
我们想查询的用户
+----+------+------+-------------+
| id | name | age | email |
+----+------+------+-------------+
| 2 | mike | 30 | 1111@qq.com |
+----+------+------+-------------+但是我们使用名字 ' or 1='1 ,并不是真正的名字,单元测试进行运行的时候却发现
就类似于在mysql中的这种效果,
这就是sql注入,当我们把UserMapper.xml中的文件改成#{},就没有这个顾虑了。
like查询
<select id="getListByName" resultType="com.example.demo1014.entity.UserInfo">select* from userinfo where name like LIKE CONCAT('%', #{name}, '%') </select>
这里使用concat函数,不能使用'%#{name}%'——>相当于
mysql> select* from userinfo where name like '%m%'; +----+-------+------+------------------+ | id | name | age | email | +----+-------+------+------------------+ | 2 | mike | 30 | 1111@qq.com | | 7 | smith | 888 | 792738927@qq.com | +----+-------+------+------------------+ 2 rows in set (0.00 sec)mysql> select* from userinfo where name like '%'m'%'; ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'm'%'' at line 1
mapper中接收结果的参数
resultType和resultMap
resultType 适用于简单的映射场景,而 resultMap 更加灵活、可定制化,可以实现更高级的映射需求 .不过resultMap使用前要先声明。
resultMap的使用场景: 字段名和属性名不一样(也可以使用as别名)
我们程序中写的字段如username,而mysql表中是name。
这样就不能用resultType,
<resultMap id="baseMap" type="com.example.demo1014.entity.UserInfo"><id column="id" property="id"></id><result column ="name" property="username"></result><result column ="age" property="age"></result><result column="email" property="email"></result></resultMap><select id="getAll" resultMap="baseMap">select* from userinfo;</select>
更简单的解决——>as
select id,name as username ,age,email from userinfo
多表查询
使用left join
<select id="getUserListWithOrders" resultMap="userWithOrdersMap">SELECT u.*, o.*FROM users u LEFT JOIN orders o ON u.id = o.user_id </select>