MyBatis—操作数据库(三)

简介: MyBatis—操作数据库(三)

在 xml 中实现方法


<delete id="delUserInfo">
    delete from userinfo where id = #{id};
</delete>

单元测试验证效果


不污染数据库进行单元测试


利用注解@Transactional

注解@Transactional既可以修饰类, 也可以修饰方法


举个栗子🌰

要求

测试删除功能是否正常 + 数据库中的数据不会被删除

(即不污染数据库进行单元测试)

此时可以利用注解@Transactional

删除功能正常🍂

数据库中的数据不会被删除🍂

🔎对比 # 与 $


根据 id 查询用户信息


/**
* 根据 Id 查询用户信息
* @author bibubibu
* @date 2023/7/2
*/
UserInfo getUserById(@Param("id") Integer id);

使用 #🍂

<select id="getUserById" resultType="com.example.demo.entity.UserInfo">
    select * from userinfo where id = #{id}
</select>

使用 $🍂

<select id="getUserById" resultType="com.example.demo.entity.UserInfo">
    select * from userinfo where id = ${id}
</select>

运行结果🍂

均可正常运行

根据 username 查询用户信息


/**
* 根据 username 查询用户信息
* @author bibubibu
* @date 2023/7/3
*/
List<UserInfo> getUserByName(@Param("username") String username);

使用 #🍂

<select id="getUserByName" resultType="com.example.demo.entity.UserInfo">
    select * from userinfo where username = #{username}
</select>

使用 $🍂

<select id="getUserByName" resultType="com.example.demo.entity.UserInfo">
    select * from userinfo where username = ${username}
</select>

运行结果🍂

使用 # 正常运行

使用 $ 无法正常运行

根据 id 进行排序


排序有 2 种类型

  • 升序 → asc
  • 降序 → desc

此处以降序举例

/**
* 根据 Id 进行排序
* @author bibubibu
* @date 2023/7/3
*/
List<UserInfo> getUserOrderById(@Param("order") String order);

使用 #🍂

<select id="getUserOrderById" resultType="com.example.demo.entity.UserInfo">
    select * from userinfo order by id #{order}
</select>

使用 $🍂

<select id="getUserOrderById" resultType="com.example.demo.entity.UserInfo">
    select * from userinfo order by id ${order}
</select>

运行结果🍂

使用 # 无法正常运行

使用 $ 正常运行

总结


  • #{} → 编译预处理, 不存在 SQL 注入问题
  • ${} → 直接替换, 存在 SQL 注入问题

使用 $ 的注意事项🍂

一定是可穷举的值(例如关键字…), 在使用之前要对传递的值进行安全性验证


编译预处理是指 MyBatis 在处理 #{ } 时, 将 SQL 中的 #{ } 替换为 ?

直接替换是指 MyBatis 在处理 #{ } 时, 将 SQL 中的 #{ } 替换为参数的值

  • 根据 id 查询用户信息🍂
  • #{} → 将#{id}替换为?, 参数为 Integer id, 赋值 ? 为对应类型的值(数值型数据无需'')
  • ${}→ 将${id}替换为对应的 Integer id 的值
  • 即针对数值形数据, #{}无需添加''(也可理解为直接替换的一种方式), 因此利用#可以运行成功
  • select * from userinfo where id = 1(✔)
  • 即针对数值形数据, ${}直接替换, 因此利用$可以运行成功
  • select * from userinfo where id = 1(✔)
  • 根据 username 查询用户信息🍂
  • #{} → 将#{username}替换为?, 参数为 String username, 赋值 ? 为对应类型的值(字符串型数据需'')
  • ${}→ 将${username}替换为对应的 String username 的值
  • 即针对字符串型数据, #{}会添加'', 因此利用#可以运行成功
  • select * from username where username = 'Tom'(✔)
  • 即针对字符串型数据, ${}直接替换, 因此利用$无法运行成功
  • select * from username where username = Tom(✘)
  • 根据 id 进行排序🍂
  • #{} → 将#{order}替换为?, 参数为 String order, 赋值 ? 为对应类型的值(字符串型数据需'')
  • ${}→ 将${order}替换为对应的 String order 的值
  • 即针对字符串型数据, #{}会添加'', 因此利用#无法运行成功(关键字无需添加'')
  • select * from userinfo order by id 'desc'(✘)
  • 即针对字符串型数据, ${}直接替换, 因此利用$可以运行成功(关键字无需添加'')
  • select * from userinfo order by id desc(✔)

简单来说就是针对不同的内容

#{}可能会对参数添加''(字符串型), 也可能是直接替换(数值型)

${}直接替换为对应参数的内容


SQL 注入


既然 # 对于字符串型数据会添加'', 那使用 $ 时对于字符串型手动添加''不可以么

使用 $ 是不安全的, 可能会引起 SQL 注入问题


什么是 SQL 注入?

举个栗子🌰

userinfo 表中的内容🍂

定义一个 login 方法🍂

UserInfo login(@Param("username") String username, @Param("password") String password);

实现该方法🍂

(对于字符串型手动添加'')

<select id="login" resultType="com.example.demo.entity.UserInfo">
    select * from userinfo where username = '${username}' and password = '${password}'
</select>

单元测试查看结果🍂

登录成功

修改密码后查看结果🍂

登录失败

利用 SQL 注入登录(使用错误的密码)🍂

登录成功

注意此时的密码

String password = "' or 1 = '1";

最终生成的 SQL 语句

select * from userinfo where username = 'admin' and password = '' or 1 = '1'

划分为 2 部分(优先级 → and > or)

username = 'admin' and password = '' / 1 = '1'

因此可以成功登录

🌸上述即为 SQL 注入, 因此推荐使用 # 而不是 $🌸


🔎like 查询


like 查询 → 此处使用的数据表为 userinfo(用户) 表

数据表中的数据

根据 username 查询用户信息


在 Interface 中定义方法🍂

/**
* Like 查询
* @author bibubibu
* @date 2023/7/3
*/
List<UserInfo> getListByName(@Param("username") String username);

在 xml 中实现方法🍂

<select id="getListByName" resultType="com.example.demo.entity.UserInfo">
    select * from userinfo where username like '%#{username}%'
</select>

单元测试验证效果🍂

Error → 这是因为使用 # 处理字符串类型时, SQL 语句会添加''

即上述 SQL 语句变为select * from userinfo where username like '%'a'%'

期望的效果是select * from userinfo where username like '%a%'

可能有的小伙伴会说, 那可以用 $ 处理呀

不可以, 还记得上面说的使用 $ 时的注意事项么

使用 $ 时的注意事项 → 一定是可穷举的值(例如关键字…), 而 username 无法穷举, 因此应避免使用 $

使用 # 时的解决办法


解决办法 → 利用 concat() 进行拼接

<select id="getListByName" resultType="com.example.demo.entity.UserInfo">
    select * from userinfo where username like concat('%', #{username}, '%')
</select>

对比🍂

select * from userinfo where username like '%#{username}%'

select * from userinfo where username like concat('%', #{username}, '%')

单元测试验证效果🍂

目录
打赏
0
0
0
0
1
分享
相关文章
【潜意识Java】MyBatis中的动态SQL灵活、高效的数据库查询以及深度总结
本文详细介绍了MyBatis中的动态SQL功能,涵盖其背景、应用场景及实现方式。
632 6
Java后端开发-使用springboot进行Mybatis连接数据库步骤
本文介绍了使用Java和IDEA进行数据库操作的详细步骤,涵盖从数据库准备到测试类编写及运行的全过程。主要内容包括: 1. **数据库准备**:创建数据库和表。 2. **查询数据库**:验证数据库是否可用。 3. **IDEA代码配置**:构建实体类并配置数据库连接。 4. **测试类编写**:编写并运行测试类以确保一切正常。
240 2
深入 MyBatis-Plus 插件:解锁高级数据库功能
Mybatis-Plus 提供了丰富的插件机制,这些插件可以帮助开发者更方便地扩展 Mybatis 的功能,提升开发效率、优化性能和实现一些常用的功能。
1088 26
深入 MyBatis-Plus 插件:解锁高级数据库功能
|
8月前
|
MyBatis-Plus条件构造器:构建安全、高效的数据库查询
MyBatis-Plus 提供了一套强大的条件构造器(Wrapper),用于构建复杂的数据库查询条件。Wrapper 类允许开发者以链式调用的方式构造查询条件,无需编写繁琐的 SQL 语句,从而提高开发效率并减少 SQL 注入的风险。
186 2
MyBatis-Plus条件构造器:构建安全、高效的数据库查询
canal-starter 监听解析 storeValue 不一样,同样的sql 一个在mybatis执行 一个在数据库操作,导致解析不出正确对象
canal-starter 监听解析 storeValue 不一样,同样的sql 一个在mybatis执行 一个在数据库操作,导致解析不出正确对象
springboot学习五:springboot整合Mybatis 连接 mysql数据库
这篇文章是关于如何使用Spring Boot整合MyBatis来连接MySQL数据库,并进行基本的增删改查操作的教程。
1580 0
springboot学习五:springboot整合Mybatis 连接 mysql数据库
表白墙/留言墙 —— 中级SpringBoot项目,MyBatis技术栈MySQL数据库开发,练手项目前后端开发(带完整源码) 全方位全步骤手把手教学
本文是一份全面的表白墙/留言墙项目教程,使用SpringBoot + MyBatis技术栈和MySQL数据库开发,涵盖了项目前后端开发、数据库配置、代码实现和运行的详细步骤。
214 0
表白墙/留言墙 —— 中级SpringBoot项目,MyBatis技术栈MySQL数据库开发,练手项目前后端开发(带完整源码) 全方位全步骤手把手教学
解决:Mybatis-plus向数据库插入数据的时候 报You have an error in your SQL syntax
该博客文章讨论了在使用Mybatis-Plus向数据库插入数据时遇到的一个常见问题:SQL语法错误。作者发现错误是由于数据库字段中使用了MySQL的关键字,导致SQL语句执行失败。解决方法是将这些关键字替换为其他字段名称,以避免语法错误。文章通过截图展示了具体的操作步骤。
在vue页面引入echarts,图表的数据来自数据库 springboot+mybatis+vue+elementui+echarts实现图表的制作
这篇文章介绍了如何在Vue页面中结合SpringBoot、MyBatis、ElementUI和ECharts,实现从数据库获取数据并展示为图表的过程,包括前端和后端的代码实现以及遇到的问题和解决方法。
在vue页面引入echarts,图表的数据来自数据库 springboot+mybatis+vue+elementui+echarts实现图表的制作
AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等

登录插画

登录以查看您的控制台资源

管理云资源
状态一览
快捷访问