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

标签:Mybatis,#{},${}
0
投稿

猜你喜欢

  • Spring中Bean的三种实例化方式详解

    2023-07-28 12:37:07
  • Java解析XML格式数据的方法详解

    2022-03-25 09:28:25
  • Java利用栈实现简易计算器功能

    2022-05-08 16:57:25
  • JAVA实现KMP算法理论和示例代码

    2021-08-06 07:13:44
  • java实现KFC点餐小程序

    2022-12-11 21:06:51
  • springboot实现多模块项目添加一新模块

    2021-09-22 16:43:09
  • Android Hilt依赖注入的使用讲解

    2023-11-23 02:13:50
  • C#导出生成excel文件的方法小结(xml,html方式)

    2023-10-03 16:32:26
  • WinForm 自动完成控件实例代码简析

    2022-06-28 22:02:24
  • 详解JAVA高质量代码之数组与集合

    2022-03-31 16:42:07
  • Java从JDK源码角度对Object进行实例分析

    2022-04-09 20:12:22
  • HashMap的get()方法的NullPointerException问题

    2023-09-23 07:24:12
  • Android Studio多渠道打包的配置方法

    2023-06-15 23:19:48
  • java实现倾斜水印铺满整张图

    2023-12-24 22:34:21
  • Springboot实现通用Auth认证的几种方式

    2023-08-05 20:54:58
  • Java文件读写IO/NIO及性能比较详细代码及总结

    2021-11-28 12:56:30
  • 详解Spring依赖注入的三种方式使用及优缺点

    2023-06-09 18:29:00
  • Spring Boot非Web项目运行的方法

    2021-07-23 13:05:32
  • Unity使用LineRender断笔写字

    2023-01-07 09:29:38
  • Android开发升级AGP7.0后的一些适配方法技巧

    2022-10-22 17:41:22
  • asp之家 软件编程 m.aspxhome.com