广告
返回顶部
首页 > 资讯 > 后端开发 > Python >mybatis中${}和#{}取值的区别分析
  • 748
分享到

mybatis中${}和#{}取值的区别分析

2024-04-02 19:04:59 748人浏览 独家记忆

Python 官方文档:入门教程 => 点击学习

摘要

mybatis作为一个轻量级的ORM框架,应用广泛,其上手使用也比较简单;一个成熟的框架,必然有精巧的设计,值得学习。 在使用mybatis框架时,在sql语句中获取传入的参数有如下

mybatis作为一个轻量级的ORM框架,应用广泛,其上手使用也比较简单;一个成熟的框架,必然有精巧的设计,值得学习

在使用mybatis框架时,在sql语句中获取传入的参数有如下两种方式:

  • ${paramName}
  • #{paramName}

那如何理解这两种传参方式呢?如下带你走近背后的奥义。

先来回顾下原生Jdbc查询:


public static void main(String[] args) throws Exception {

  // sql语句
  String sql = "select id,name from customer limit 2";
  // 1.加载驱动, 此处使用的Mysql驱动包是8.0版本, 若为5.0+版本, 请修改以下类路径
  Class.forName("com.mysql.cj.jdbc.Driver");
  // 2.获取数据库连接
  String url = "jdbc:mysql://localhost:3306/work?useSSL=false&useUnicode=true" +
    "&characterEncoding=UTF-8&useJDBCCompliantTimezoneShift=true" +
    "&useLegacyDatetimeCode=false&serverTimezone=UTC";
  Connection conn = DriverManager.getConnection(url,"root", "123456");
  // 3、获得可以执行sql语句的对象
  Statement st = conn.createStatement();
  // 4、使用对象去执行SQL语句
  ResultSet rs = st.executeQuery(sql);
  // 5、处理sql语句返回的结果集
  while(rs.next()){
    // 获得一行数据
    Integer id = rs.getInt("id");
    String name = rs.getString("name");
    System.out.println("sql查询: id = " + id + " , name = " + name);
  }
  // 6、释放资源
  rs.close();
  st.close();
  conn.close();
}

控制台打印:

sql查询: id = 1 , name = 李白
sql查询: id = 2 , name = 杜甫

了解Jdbc的人会知道,其中第3、4步两条语句也可以换成如下两条:


// 3.创建 PreparedStatement 对象去执行sql
PreparedStatement preparedStatement = conn.prepareStatement(sql);
// 4.执行sql语句
ResultSet rs = preparedStatement.executeQuery();

我们来比较下区别:

  • 创建 PreparedStatement 对象时就把sql语句传入,在执行语句时就不用传入sql了;而 Statement 则刚好相反

这就引出了预编译的概念:

  • 如果使用PreparedStatement 对象,那么在执行第3步时,你既然已经传入了sql,则相当于这条sql会被数据库编译(数据库对sql语句的编译也是相当复杂的),所以在第4步执行的时候就不用再传入sql了,因为数据库已经知道你要执行的sql了,你只需要传入参数即可;
  • 如果使用Statement对象,那容易理解,数据库就没有提前去解析你的sql,因为你创建对象时都没有传入;当执行sql时,数据库再编译与执行。

看到这里,可能也仅仅只记住了一个预先编译sql了,一个没有预先编译,并没有了解到对于实际开发中的区别,以下将会举例说明。

那是否PreparedStatement对象这种方式就一定比Statement对象方式好?

没有那么绝对的事,大家要理解:

​ PreparedStatement对象的好处是,sql已经提前编译好,剩下的工作就是传入参数即可,编译好的sql可以复用,传入不同的参数,则数据库就将相应的参数填入编译好的sql。而Statement对象就是每次都要传入sql,丢给数据库去编译再执行;但是创建PreparedStatement对象的开销是比Statement对象大的。

​ 回归到日常开发中,以上的区别我们压根也不用在意,事实上,百分之九十的场景我们使用的是PreparedStatement对象的方式,可能平时没有感知到,因为这是框架已经封装了。再者,当系统出现性能问题时,也绝对不会是因为这两个对象的原因。

​以上简单回顾了下Jdbc中PreparedStatement与Statement对象;

可以预料,mybatis中${} 与 #{} 这两种取值方式就是相当于对应着PreparedStatement和Statement对象的区别了。

  • #{} 传参,代表sql已经预编译好了,你传入的参数真的就仅仅是参数!
  • ${} 传参,随便你传,传完了之后我再统一编译

那具体在使用中有什么不同呢?理解如下两种场景:

1.看如下service和sql语句


@Override
public List<Map<String, Object>> listUser() {
  String param = " and name = '李白'";
  return indexMapper.listUser(param);
}
<select id="listUser" resultType="map">
  select * from customer
  where 1 = 1 #{param}
</select>

以上代码能正常查询吗?

### Error querying database.  Cause: java.sql.SQLSyntaxErrorException: 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 '' and name = \'李白\''

不能!会报sql语句规则错误,之前说了,#{} 取值代表sql已经编译好了,你传入的仅仅是参数

对应上面示例:

​ sql是指:select * from customer where 1 = 1

​ 参数是指:and name = '李白'

此时sql可以正确运行,但是带上传入的参数就不行了,要理解你传入的真的仅仅是参数,不要和前面的sql混了。

但是这明显不对,因为想表达的其实是这样:

​ sql是指:select * from customer where 1 = 1 and name = ?

​ 参数是指:'李白'

此时把参数替换进占位符是可以正常运行整个语句的。

所以此时应该用 ${param},因为用${}就没有提前编译好哪些是属于sql。

此示例表明:当你传入的参数不仅仅是参数,其实是一小段sql,想和原sql拼接在一起时,那就得用${}传参,相当于拼接好了之后丢给

数据库去解析整个语句;

sql中的问号代表参数占位符,这也是PreparedStatement对象特点之一,会将你传入的参数一一替换进占位符

反之如下:


@Override
public List<Map<String, Object>> listUser() {
  String param = "李白";
  return indexMapper.listUser(param);
}
<select id="listUser" resultType="map">
  select * from customer
  where 1 = 1 and name = #{param}
</select>

这种情况使用 #{} 就是对的了,因为传入的参数仅仅就是参数,替换进sql语句中即可。

2.对参数类型的影响


@Override
public List<Map<String, Object>> listUser() {
  String param = "李白";
  return indexMapper.listUser(param);
}
<select id="listUser" resultType="map">
  select * from customer
  where 1 = 1 and name = ${param}
</select>

以上代码能执行成功吗?

按理说,传入的仅仅是参数,不管是否预编译都应该能执行,但是实际还是会报错。

这是执行时打印出的sql语句:


select * from customer where 1 = 1 and name = 李白

显然,问题就在于参数没有加单引号,name字段是字符串类型,传入的也是字符串,偏偏mybatis转换之后没有加单引号。

所以当传入字符串类型参数时,应该用 #{} 取值,此时会自动加上单引号。

再看下面这种语句:


@Override
public List<Map<String, Object>> listUser() {
  String param = "name";
  return indexMapper.listUser(param);
}
<select id="listUser" resultType="map">
  select * from customer
  where 1 = 1
  order by ${param} desc
</select>

此时传入的参数是要排序的字段名称,之前说了,如果采用#{} 取值,则实际是会自动加上单引号的,但是order by后面的排序字段需要单引号吗?

不需要,所以这种情况只能使用 ${} 取值。

你可能会发现此处用 #{} 取值也不会报错,那是因为mysql支持这种写法,但是查询的结果并不对。

​ 日常开发中,只要能理解上述两种情形,那么就能正确使用 ${} 和 #{},由于这两种方式取值原理的区别,也容易明白 #{} 这种方式是可以防止sql注入的。

总结

到此这篇关于mybatis中${}和#{}取值区别分析的文章就介绍到这了,更多相关mybatis ${}和#{}取值区别内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: mybatis中${}和#{}取值的区别分析

本文链接: https://www.lsjlt.com/news/135497.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • mybatis中${}和#{}取值的区别分析
    mybatis作为一个轻量级的ORM框架,应用广泛,其上手使用也比较简单;一个成熟的框架,必然有精巧的设计,值得学习。 在使用mybatis框架时,在sql语句中获取传入的参数有如下...
    99+
    2022-11-12
  • mybatis collection和association的区别解析
    目录1.collection标签1.1 相关代码和运行结果1.2 collection部分源码解析1.3 <collection>和<association>...
    99+
    2022-11-13
  • Mybatis中#和$的区别
    在使用mybatis框架开发项目编写SQL语句的时候,经常需要用到变量替换值,那么用来替换变量值的操作经常用到$和#这两个符号,同样在一些Java面试中也经常被问到它们的区别。那么它们在使用上面有什么区别呢?下面根据使用情况分析总结,两者的...
    99+
    2023-09-02
    大数据 java mybatis mysql
  • mybatis中的#和$的区别
    #相当于对数据 加上 双引号,$相当于直接显示数据  #将传入的数据都当成一个字符串,会对自动传入的数据加一个双引号。如:order by #user_id#,如果传入的值是111,那么解析成sql时的值为order by "11...
    99+
    2023-06-02
  • mybatis中#{}和${}的区别详解
    目录一、MyBatis中${}和#{}的区别1.1 ${}和#{}演示1.2 SQL注入问题1.3 ${}和#{}的区别1.4 #{}底层是如何防止SQL注入的?1.4.1 网上的答...
    99+
    2022-11-13
  • MyBatis中的#{}和${}有什么区别
    这篇文章主要介绍了MyBatis中的#{}和${}有什么区别,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。前言在MyBatis 的映射配置文件中,动态传递参数有两种方式:#{...
    99+
    2023-06-21
  • Mybatis中#和$的区别是什么
    这篇文章主要介绍“Mybatis中#和$的区别是什么”,在日常操作中,相信很多人在Mybatis中#和$的区别是什么问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Mybatis中#和$的区别是什么”的疑惑有所...
    99+
    2023-06-22
  • 分析 Vue 中的 computed 和 watch 的区别
    目录一、computed介绍1.1、get 和 set 用法 1.2、计算属性缓存二、watch介绍三、两者区别3.1、对于 computed3.2、对于 watch四、应...
    99+
    2022-11-12
  • Android Activity中onStart()和onResume()的区别分析
    本文分析了Android Activity中onStart()和onResume()的区别。分享给大家供大家参考,具体如下: 首先你要知道Activity的四种状态: ① Ac...
    99+
    2022-06-06
    activity Android
  • 分析ES5和ES6的apply区别
    目录概述函数签名可选参数非严格模式异常处理实际使用总结概述 众所周知, ES6 新增了一个全局、内建、不可构造的Reflect对象,并提供了其下一系列可被拦截的操作方法。其中一个便是...
    99+
    2022-11-12
  • 详解Mybatis中javaType和ofType的区别
    目录一. 背景描述二. 情景再现1. 实体类2.BookMapper.xml映射文件3. 核心配置4. 测试代码5. 修改实体类6. 添加映射文件BookTypeMapper.xml...
    99+
    2023-05-20
    Mybatis javaType和ofType
  • Android开发中setContentView和inflate的区别分析
    本文实例讲述了Android开发中setContentView和inflate的区别。分享给大家供大家参考,具体如下: 一般用LayoutInflater做一件事:inflat...
    99+
    2022-06-06
    android开发 Android
  • C++中左值和右值的区别详解
    目录左值右值定义:特性左值引用, 右值引用总结左值右值定义: 左值指的是既能够出现在等号左边也能出现在等号右边的变量(或表达式),右值指的则是只能出现在等号右边的变量(或表达式). ...
    99+
    2022-11-13
  • 如何分析bootstrap和vue的区别
    今天就跟大家聊聊有关如何分析bootstrap和vue的区别,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。区别:1、Bootstrap是基于HTML...
    99+
    2022-10-19
  • 浅析Oracle和Mysql分页的区别
    一、Mysql使用limit分页 select * from stu limit m, n; //m = (startPage-1)*pageSize,n = pageSize ...
    99+
    2022-10-18
  • 浅析Mysql和Oracle分页的区别
    目录mysql使用limit进行分页oracle使用rownum进行分页Mysql与Oracle级联查询Mysql省市区级联查询Mysql与Oracle插入数据存在修改不存在新增MySQL使用limit进行分页 sele...
    99+
    2022-12-07
    Mysql和Oracle分页区别 MysqlOracle分页
  • 怎么分析cookie和session的区别
    这篇文章给大家介绍怎么分析cookie和session的区别,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。1,cookie保存在浏览器(客户端)中,服务器知道数据,cookie可以通过工具随意修改,不安全2,Sessi...
    99+
    2023-06-04
  • MongoDB和mysql的区别对比分析
    目录一.什么是MongoDB二.什么是Mysql三,区别一.什么是MongoDB MongoDB 是一个基于分布式文件存储的数据库。由 C++ 语言编写,是一个开源数据库系统。旨在为...
    99+
    2023-01-31
    MongoDB和mysql的区别 MongoDB mysql区别
  • Android中的Dalvik和ART详解及区别分析
    要想知道Dalvik和ART区别分析,首先我们要分别知道这两者是什么? 什么是Dalvik? Dalvik是Google公司自己设计用于Android平台的虚拟机。 Dalvi...
    99+
    2022-06-06
    art Android
  • Android编程中@id和@+id的区别分析
    本文分析了Android编程中@id和@+id的区别。分享给大家供大家参考,具体如下: Android中的组件需要用一个int类型的值来表示,这个值就是组件标签中的id属性值。...
    99+
    2022-06-06
    Android
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作