Mybatis之#{}与${}的区别使用详解
作者:Javxuan 发布时间:2023-03-24 01:55:21
1.两种取值方式的差异
mapper.xml映射文件
<select id="selectEmployeeByCondition2" resultMap="empResultMap" databaseId="mysql">
select * from t_emp WHERE emp_id=${id} and emp_name=#{name}
</select>
java查询代码 params 为 id=1 ,name=”小红”
@Test
public void testSelect() {
InputStream resourceAsStream = ConfigTest.class.getResourceAsStream("../classes/mybatis-config.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
EmployeeMapper mapper2 = sqlSession.getMapper(EmployeeMapper.class);
Employee employee2 = mapper2.selectEmployeeByCondition2(1,"xiaohong");
System.out.println(employee2);
}
结果
==> Preparing: select * from t_emp WHERE emp_id=1 and emp_name=?
==> Parameters: xiaohong(String)
<== Columns: emp_id, emp_name, emp_email, emp_tel, emp_dep, emp_status
<== Row: 1, xiaohong , 123@qq.com, 123, 1, 0
<== Total: 112345
1.1 #{}
从上述代码可以看出 #{} 在原生jdbc语句中会用 ?占位符来表示。这样做可以防止sql注入
1.2${}
从上述代码可以看出 ${} 是直接把param 拼到原生sql上
2.什么时候该使用什么方式
从上述示例可以看出 #{} 与${}的作用都是取值,同时#{}还可以防止sql注入更安全。是否表示在以后代码中就用#{}呢? 当然不是这样的,比如某电商系统的订单表数据量太庞大,不得以分表来保存数据。该电商的工程师最后决定将该表按年月进行分表(t_order_201701,t_order_201702…)。这个时候我们该采用那个中方式进行查询呢,如我要查询17年6月份的全部订单?
你可能想当然的认为这个容易,只要把年月动态传入到sql中就可以了如下:
<select id="selectOrderByCondition" resultMap="orderResultMap" databaseId="mysql">
select * from t_order_#{createYM} WHERE DATE_FORMAT(create_date,'%Y%m')=${createYM}+''
</select>123
结果
==> Preparing: select * from from t_order_? WHERE DATE_FORMAT(create_date,'%Y%m')='201706'
==> Parameters: 201706(Integer)12
很显然该语句是执行不了的,此时就要采用${}
<select id="selectOrderByCondition" resultMap="orderResultMap" databaseId="mysql">
select * from t_order_${createYM} WHERE DATE_FORMAT(create_date,'%Y%m')=${createYM}+''
</select>
拼装的原生jdbcsql
==> Preparing: select * from from t_order_201706 WHERE DATE_FORMAT(create_date,'%Y%m')='201706'
==> Parameters: 201706(Long)12
很显然这条sql可以执行。
3.总结
动态 sql 是 mybatis 的主要特性之一,在 mapper 中定义的参数传到 xml 中之后,在查询之前 mybatis 会对其进行动态解析。mybatis 为我们提供了两种支持动态 sql 的语法:#{} 以及 ${} 。
1、#相当于对数据 加上 双引号,$相当于直接显示数据。
2、#{} : 根据参数的类型进行处理,比如传入String类型,则会为参数加上双引号。#{} 传参在进行SQL预编译时,会把参数部分用一个占位符 ? 代替,这样可以防止 SQL注入。
3、${} : 将参数取出不做任何处理,直接放入语句中,就是简单的字符串替换,并且该参数会参加SQL的预编译,需要手动过滤参数防止 SQL注入。
4、因此 mybatis 中优先使用 #{};当需要动态传入 表名或列名时,再考虑使用 ${} , 比较特殊,他的应用场景是需要动态传入表名或列名时使用,mybatis 排序时使用orderby动态参数时需要注意,用$而不是#
来源:https://blog.csdn.net/u014297148/article/details/79516966


猜你喜欢
- 引言当我们通过@ConfigurationProperties注解实现配置 bean的时候,如果默认的配置属性转换无法满足我们的需求的时候,
- 如论实施敏捷的团队,或者实施 DevOps 的团队,通过自动化测试提高测试效率和软件质量都是其共同的选择。UI 自动化测试是自动化化测试当中
- 前言在实际工作中,重试机制是一个很常见的场景,比如:发送消息失败,下载网络文件失败等…,因为这些错误可能是网络波动造成
- 前言最近在开发一个IM项目的时候有一个需求就是,好友搜索功能。即在EditText中输入好友名字,ListView列表中动态展示刷选的好友列
- 写在前面在这里,我们将会学习怎么利用java8 快速的打印出需要打印的元素利用stream打印元素在Java中,有三种不同的方法来打印Jav
- 先看代码://设置可以同时处于活动状态的线程池的请求数目。 bool pool = ThreadPool.SetMaxThreads(8,
- 本文实例讲述了C#实现字符串与图片的Base64编码转换操作。分享给大家供大家参考,具体如下:using System;using Syst
- 1. json数据类型类型描述Number数字型String字符串型Boolean布尔型Array数组Object对象null空值(1)js
- renameTo方法public boolean renameTo(File dest),File类中的renameTo方法可以操作文件或目
- 场景:假设每次我们去超市购物,我们都会推一个购物车,有水果、蔬菜、肉类三种商品,提供给我们选择,那么这时候,如果使用装饰器模式,应该如何实现
- 题主要区分清楚内码(internal encoding)和外码(external encoding)就好了。内码是程序内部使用的字符编码,特
- 首先:看问题图,如下可以激活ide的网址很多,估计是个团队或者个人,直接买了全部产品的一年的有效期。而且还是会一直更新下去的。因为,后来我自
- 一、 搭建struts2环境在myeclipse下,右击项目->MyEclipse->Project Facets->in
- 本文实例讲述了Android编程设计模式之抽象工厂模式。分享给大家供大家参考,具体如下:一、介绍抽象工厂模式(Abstract Factor
- java操作Excel数据在 平时 可以使用IO流对Excle进行操作但是现在使用更加方便的第三方组件来实现使用场景1、将用户信息导出为Ex
- 谷歌有专门的SDK来完成VR,我这次以一个全景图片的例子来说一下这个SDK实现VR的基本过程,首先全景图片就是百度地图里的那样,能够看到周围
- Android中SQLite 使用方法详解现在的主流移动设备像android、iPhone等都使用SQLite作为复杂数据的存储引擎,在我们
- 本文实例讲述了C# SQLite事务操作方法。分享给大家供大家参考,具体如下:在 C#中执行Sqlite数据库事务有两种方式:SQL代码和C
- 本文实例讲述了Java使用DateFormatter格式化日期时间的方法。分享给大家供大家参考,具体如下:Java版本:1.8开始impor
- 本文实例讲述了WCF实现的计算器功能。分享给大家供大家参考,具体如下:对于WCF,我们有了前面的理论基础,今天通过一个计算器的实例主要给大家