当前位置: 首页 > news >正文

MyBatis 中 #{} 和 ${} 的区别看完这篇文章一目了然

我们知道 MyBatis 中对于参数的赋值有两种方式, 一种是使用 #{}, 一种是使用 ${}, 这两种参数赋值的方式对于有些情况都可以正常使用, 但是针对某些场景, ${} 却会报错. 本篇文章主要介绍两者的区别, 通过例子的方式来说明什么场景下 ${} 不适用, 什么场景下又不得不使用 ${}.

#{} 和 ${} 的区别

  • 1 例子
    • 🌰1.1: 根据 id 来查询一条用户的数据
    • 🌰1.2: 根据用户姓名来查询一条用户的数据
    • 🌰1.3: ${} 使用场景
  • 2 总结

1 例子

🌰1.1: 根据 id 来查询一条用户的数据

首先在 mapper 层写一个接口, 根据用户的 id 来查询用户;

@Mapper
public interface UserMapper {
    // 根据用户 Id 查询用户
    // @Param("id") 代表 Integer id 这个参数在 xml 文件中使用 id 就能获取到
    public UserInfo getUserById(@Param("id") Integer id);
}

xml 代码如下:

<?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.demo.mapper.UserMapper">
    <!-- 根据 id 查询用户信息 -->
    <select id="getUserById" resultType="com.example.demo.model.UserInfo">
        select * from userinfo where id=#{id}
    </select>
</mapper>

关于数据库的表格(数据库表格中已经有数据)以及实体类不再描述, 先看一个单元测试的结果:

@SpringBootTest
class UserMapperTest {
    @Resource
    private UserMapper userMapper;

    @Test
    void getUserById() {
        UserInfo userInfo = userMapper.getUserById(1);
        Assertions.assertNotNull(userInfo);
    }
}

运行结果:
在这里插入图片描述
然后将xml 文件中改成 ${}:
在这里插入图片描述
运行结果则如下:
在这里插入图片描述
根据上面的两种运行结果, 总结如下:
#{} 是预处理执行, 而 ${} 是直接替换的方式进行查询.

🌰1.2: 根据用户姓名来查询一条用户的数据

首先在 mapper 层写一个接口, 根据用户的姓名来查询用户;

@Mapper
public interface UserMapper {
    // 根据用户 username 查询用户
    public UserInfo getUserByName(@Param("username") String username);
}

xml 代码如下:

<?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.demo.mapper.UserMapper">
    <!-- 根据 username 查询用户信息 -->
    <select id="getUserByName" resultType="com.example.demo.model.UserInfo">
        select * from userinfo where username=#{username}
    </select>
</mapper>

关于数据库的表格(数据库表格中已经有数据)以及实体类不再描述, 先看一个单元测试的结果:

@SpringBootTest
class UserMapperTest {
    @Resource
    private UserMapper userMapper;

    @Test
    void getUserByName() {
        UserInfo userInfo = userMapper.getUserByName("张三");
        Assertions.assertNotNull(userInfo);
    }
}

运行结果如下:
在这里插入图片描述
然后将xml 文件中改成 ${}:
在这里插入图片描述
运行结果则如下:
在这里插入图片描述
根据上面的两种结果, 可以总结如下:
#{} 对于根据姓名来查找一条用户信息没有任何影响, 而 ${} 则报错, 原因我们可以看的出来张三没有加上" ", 因此查不到数据. 这时候两种赋值方式就看出了区别.

🌰1.3: ${} 使用场景

虽然我们大部分都是使用 #{} 来进行参数赋值, 但是 ${} 的出现也不是一无是处, 下面的这个场景就能展示出 ${} 的作用, 此场景又不得不使用 ${}.
查询数据库中的列表信息, 并且按照升序或者降序打印, 代码如下:
首先在 mapper 层写一个接口, 根据创建时间的升序来查询用户列表;

@Mapper
public interface UserMapper {
    // 获取列表, 根据创建时间进行升序或倒序
    public List<UserInfo> getOrderList(@Param("order") String order);

}

xml 代码如下(使用${}):

<?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.demo.mapper.UserMapper">
        <!-- 查询所有的用户信息(按照升序或者降序查找) -->
    <select id="getOrderList" resultType="com.example.demo.model.UserInfo">
        select * from userinfo order by createtime ${order}
    </select>
</mapper>

关于数据库的表格(数据库表格中已经有数据)以及实体类不再描述, 先看一个单元测试的结果:

@SpringBootTest
class UserMapperTest {
    @Resource
    private UserMapper userMapper;

    @Test
    void getOrderList() {
        List<UserInfo> list = userMapper.getOrderList("asc");
        log.info("列表: " + list);
    }
}

运行结果如下:
在这里插入图片描述
此时结果可以查得到;
然后将xml 文件中改成 #{}:
在这里插入图片描述
运行结果则如下(报错):
在这里插入图片描述
原因如下:
当传递的是一个 SQL 关键字 (SQL 命令) 的时候, 只能使用 ${}, 此时如果使用 #{}, 就会认为传递的是一个普通的值, 而不是 SQL 命令, 也就是说会自主的将 asc / desc 加上’ ', 因此将会报错, 可以看下面我在数据库中用关键字查询的命令, 如下:
在这里插入图片描述
如果对 asc 加上 ’ ', 则会报错:在这里插入图片描述

2 总结

  • 定义不同: #{} 是预处理, 而 ${} 是直接替换, 也可以说 ${} 是即时查询;
  • 使用不同: #{} 适用于所有类型的参数匹配, 但 ${} 只适用于数值类型;
  • 安全性不同: #{} 性能比较高, 并且没有安全问题, 但 ${} 存在 SQL 注入的安全问题;
  • ${} 一定要慎用, 如果非用不可, 那么一定要注意把前端用户输入的值进行安全校验 / 过滤.

相关文章:

  • 实时即未来,车联网项目之原始终端数据实时ETL【二】
  • python 的re.findall的Bug以及解决方法
  • 在Windows系统上部署DHCP服务器
  • Java多线程~CAS的原理及其应用
  • [CSS]盒子模型
  • 【 C++ 】开散列哈希桶的模拟实现
  • 阿里云数据库(RDS)查看空间使用情况
  • 【C++编程语言】之 文件操作
  • 人生模式 - 如何跟潜意识对话
  • ubuntu18.04安装redis
  • 02 LaTeX文字实战应用
  • Flash:Flash动画设计软件界面的简介、Flash AS 3.0代码编程入门教程之详细攻略
  • C语言进阶——自定义类型
  • 微信公众号网课查题系统
  • golang学习笔记系列之函数
  • ES6指北【2】—— 箭头函数
  • Angular 响应式表单之下拉框
  • Cumulo 的 ClojureScript 模块已经成型
  • java中的hashCode
  • jQuery(一)
  • MySQL QA
  • spring security oauth2 password授权模式
  • swift基础之_对象 实例方法 对象方法。
  • Vue学习第二天
  • 更好理解的面向对象的Javascript 1 —— 动态类型和多态
  • 基于webpack 的 vue 多页架构
  • 今年的LC3大会没了?
  • 理解IaaS, PaaS, SaaS等云模型 (Cloud Models)
  • 前端_面试
  • 深入 Nginx 之配置篇
  • 数组大概知多少
  • d²y/dx²; 偏导数问题 请问f1 f2是什么意思
  • AI又要和人类“对打”,Deepmind宣布《星战Ⅱ》即将开始 ...
  • mysql面试题分组并合并列
  • ​​​​​​​sokit v1.3抓手机应用socket数据包: Socket是传输控制层协议,WebSocket是应用层协议。
  • #{} 和 ${}区别
  • #我与Java虚拟机的故事#连载15:完整阅读的第一本技术书籍
  • $refs 、$nextTic、动态组件、name的使用
  • (react踩过的坑)antd 如何同时获取一个select 的value和 label值
  • (动手学习深度学习)第13章 计算机视觉---图像增广与微调
  • (独孤九剑)--文件系统
  • (多级缓存)多级缓存
  • (非本人原创)史记·柴静列传(r4笔记第65天)
  • (附源码)springboot美食分享系统 毕业设计 612231
  • (附源码)计算机毕业设计SSM疫情社区管理系统
  • (四)鸿鹄云架构一服务注册中心
  • (原創) 如何解决make kernel时『clock skew detected』的warning? (OS) (Linux)
  • .360、.halo勒索病毒的最新威胁:如何恢复您的数据?
  • .class文件转换.java_从一个class文件深入理解Java字节码结构
  • .net Application的目录
  • .Net(C#)常用转换byte转uint32、byte转float等
  • .net访问oracle数据库性能问题
  • .NET委托:一个关于C#的睡前故事
  • .w文件怎么转成html文件,使用pandoc进行Word与Markdown文件转化
  • /usr/lib/mysql/plugin权限_给数据库增加密码策略遇到的权限问题