【MyBatis】动态SQL > 重点:${...}和#{...}与resultMap和resultType的区别

news2025/1/13 13:16:41

目录

一、MyBatis动态sql

1.1 动态sql的作用

1.2 动态sql作用论证

1.2.1 条件判断:<if>

1.2.2 循环迭代:<foreach>

1.2.3 SQL片段重用

1.2.4 动态条件组合:<choose><when><otherwise>

1.2.5 <where><if> 标签

1.2.6 <set> <if> 标签

1.3 #{...}与${...}的区别⭐

1.3.1 $ 符号(sql拼接符号) 

1.3.2 # 符号(占位符) 

1.3.3 案例演示 

1.3.4 sql预编译

二、resultMap和resultType的区别⭐


一、MyBatis动态sql

1.1 动态sql的作用

        什么是动态sql?动态sql就是在不同的条件下拼接出不同的sql语句。

        作用无非就是简化sql,根据不同的条件动态生成sql语句,以实现更灵活和可复用的数据库操作。以下是动态SQL的主要作用:

  1. 条件判断:动态SQL可以根据不同的条件判断生成不同的SQL语句。例如,根据用户输入的搜索条件动态生成查询语句,只包含满足条件的字段和条件。

  2. 循环迭代:动态SQL可以在SQL语句中进行循环迭代,以处理集合或数组等数据结构。例如,可以通过循环迭代生成批量插入或更新的SQL语句。

  3. SQL片段重用:动态SQL可以定义可重用的SQL片段,以便在不同的SQL语句中引用。这样可以减少代码重复,提高代码的可维护性。

  4. 动态条件组合:动态SQL可以根据不同的条件组合生成不同的SQL语句。例如,根据用户选择的不同条件动态生成查询语句的WHERE子句。

        通过使用动态SQL,开发人员可以根据具体的业务需求灵活地生成SQL语句,避免硬编码固定的SQL语句,提高代码的可读性和可维护性。同时,动态SQL还可以减少数据库的负载,提高数据库操作的性能。

1.2 动态sql作用论证

数据库:t_mvc_book

1.2.1 条件判断:<if>

     <select id="selectBook" resultMap="BaseResultMap" parameterType="com.ycxw.model.Book">
        select * from t_mvc_book where 1=1
        <if test="bid != null">
            and bid = #{bid}
        </if>
        <if test="bname !=null">
            and bname = #{bname}
        </if>
     </select>

在这个示例动态生成查询语句的条件部分中。id属性指定了映射的唯一标识,也是映射的方法名字。

这里我判断了:

        如果bname参数不为空,则添加 AND bname = #{bname}条件;如果bid参数不为空,则添加AND bid = #{bid} 条件。

测试: 

1.2.2 循环迭代:<foreach>

作用:一般用于批量删除查询;

  • collection:我们要循环的数组或集合的名称,collection属性值分别默认用"list"、"array"代替,Map对象没有默认的属性值。但是,在作为入参时可以使用@Param(“keyName”)注解来设置自定义collection属性值,设置keyName后,list、array会失效,这是keyName就必须与collection属性名字一直,不然就会报错找不到Param;
  • item:你是用哪个字段进行循环的,我们这里用的是bid字段,所以写bid,该参数为必选项;
  • index:在list、array中,index为元素的序号索引。但是在Map中,index为遍历元素的key值,该参数为可选项;
  • open:遍历集合时的开始符号,通常与close=")"搭配使用。使用场景IN(),values()时,该参数为可选项;
  • separator:元素之间的分隔符,类比在IN()的时候,separator=",",最终所有遍历的元素将会以设定的(,)逗号符号隔开,该参数为可选项;
  • close:遍历集合时的结束符号,通常与open="("搭配使用,该参数为可选项;
    <select id="selectByBids" resultMap="BaseResultMap" parameterType="com.ycxw.model.Book">
        select * from t_mvc_book
        where bid in
        <foreach collection="bids" item="bid" open="(" close=")" separator=",">
            #{bid}
        </foreach>
    </select>

在这个示例中,通过循环迭代遍历多个书籍信息。传入的参数是一个叫bids(List集合类型),通过<foreach>标签循环遍历列表中的每个书籍对象,并生成对应的查询id语句。

如果传入的是单个属性可以使用@Param(),如果是map集合,或者单个对象就不需要。

测试: 

1.2.3 SQL片段重用

该作用于当我们经常需要使用某表的某些字段时,我们可以它分装起来,便于直接引用。

<sql id="bookColumns">
  bid, bname, price
</sql>

<select id="selectBooks" resultMap="BaseResultMap">
  SELECT <include refid="bookColumns" />
  FROM t_mvc_book
</select>

<select id="selectBooksWithPrice" resultMap="BaseResultMap">
  SELECT <include refid="bookColumns" />, info
  FROM t_mvc_book
</select>

        在这个示例中,通过<sql>标签定义了一个名为bookColumns的SQL片段,包含了书籍表的列名。然后,在不同的查询语句中通过<include>标签引用了该SQL片段,实现了列名的重用。

1.2.4 动态条件组合:<choose><when><otherwise>

<choose><when><otherwise>标签作用:选择判断,该标签相当于java中的 if...else...default语句。 

<select id="selectBooks" resultMap="BaseResultMap" parameterType="com.ycxw.model.Book">
  SELECT * FROM t_mvc_book
  WHERE 1=1
  <choose>
    <when test="bid != null">
      AND bid= #{bid}
    </when>
    <when test="bname!= null">
      AND bname = #{bname}
    </when>
    <when test="price != null">
      AND price = #{price}
    </when>
    <otherwise>
      AND info= '这是一本好书!'
    </otherwise>
  </choose>
</select>

        在这个示例中,根据不同条件生成不同的SQL语句。如果第一个条件不成立就继续往下执行,直到when条件成立后就不会执行下面的判断了。如果没有传入任何参数,则默认生成 AND info= ' 这是一本好书!' 条件。

1.2.5 <where><if> 标签

         其实在上面的<if>条件判断时还是有点弊端的,我只是在where条件后面加了 1=1,如果换成一下呢?

     <select id="selectBook" resultMap="BaseResultMap" parameterType="com.ycxw.model.Book">
        select * from t_mvc_book where
        <if test="bid != null">
            bid = #{bid}
        </if>
        <if test="bname !=null">
            and bname = #{bname}
        </if>
     </select>

如果第一条件成立那么sql语句是这样的:

 select * from t_mvc_book where bid = value ;

如果第二个呢:

 select * from t_mvc_book where and bname = value ;

这样显然是不对的,所以就用到了 <where><if>。很简单,就是把if 标签的语句放到<where></where>里面而已。

 <select id="selectBook" resultMap="BaseResultMap" parameterType="com.ycxw.model.Book">
        select * from t_mvc_book where
        <where>
            <if test="bid != null">
                and bid = #{bid}
            </if>
            <if test="bname !=null">
                and bname = #{bname}
            </if>
        </where>
  </select>

测试:

1.2.6 <set> <if> 标签

作用:选择性赋值,一般常用语update语句

        在以往的修改sql语句中,我们需要修改某个对象的所有属性,若有一项没有输入,默认该值为null。这样就有人想到既然我不需要修改那一项,我就直接去掉带字段,这样又写了一个sql语句。显然是不方便的。利用mybatis的<set><if>标签就可以实现选择性赋值,当我们传一个值就修改一个值,其他字段值不变,也不会置空。

    <update id="updateByPrimaryKeySelective" parameterType="com.ycxw.model.Book">
        update t_mvc_book
        <set>
            <if test="bname != null">
                bname = #{bname,jdbcType=VARCHAR},
            </if>
            <if test="price != null">
                price = #{price,jdbcType=REAL},
            </if>
        </set>
        where bid = #{bid,jdbcType=INTEGER}
    </update>

1.3 #{...}与${...}的区别⭐

在MyBatis中,$符号和#符号是用于参数替换的两种不同的占位符语法。它们在使用方式和替换规则上有所不同。

1.3.1 $ 符号(sql拼接符号) 

  1. $符号占位符是简单的字符串替换,不进行预编译和参数类型处理。
  2. $符号占位符直接将参数的值替换到SQL语句中,可以用于动态拼接SQL语句的部分内容。
  3. $符号占位符存在SQL注入的风险,因为参数值直接替换到SQL语句中,可能导致恶意注入攻击。
  4. 没有 '引号'

1.3.2 # 符号(占位符) 

  1. #符号占位符是预编译的占位符,会对参数进行类型处理和安全处理。
  2. #符号占位符将参数值作为预编译参数传递给数据库,可以防止SQL注入攻击。
  3. #符号占位符可以用于动态生成SQL语句的条件部分,例如WHERE子句、ORDER BY子句等。
  4. 有引号

1.3.3 案例演示 

下面是一个案例演示,展示了$符号和#符号的区别:

<select id="getBooksByPrice" parameterType="Map" resultMap="BaseResultMap">
  SELECT * FROM books
  WHERE price > ${minPrice} AND price < #{maxPrice}
</select>

在这个示例中,getBooksByPrice是一个查询操作,根据传入的minPrice和maxPrice参数来查询价格在指定范围内的书籍。

  • 如果使用$符号占位符,例如传入minPrice=10和maxPrice=20,生成的SQL语句为:
  SELECT * FROM books
  WHERE price > 10 AND price < 20

注意,$符号占位符直接将参数的值替换到SQL语句中,不进行预编译和参数类型处理。

  • 如果使用#符号占位符,例如传入minPrice=10和maxPrice=20,生成的SQL语句为:
  SELECT * FROM books
  WHERE price > ? AND price < ?

注意,#符号占位符将参数值作为预编译参数传递给数据库,可以防止SQL注入攻击。

💡💡💡小提示:表名作为变量时,必须使用 ${ }
这是因为,表名是字符串,使用 sql 占位符替换字符串时会带上单引号 '',这会导致 sql 语法错误,例如:

select * from #{tableName} where name = #{name};

 预编译之后的sql 变为:

select * from ? where name = ?;

假设我们传入的参数为 tableName = "books" , name = "ycxw",那么在占位符进行变量替换后,sql 语句变为:

select * from 'books' where name='ycxw';

上述 sql 语句是存在语法错误的,表名不能加单引号 ''(注意: 反引号 ``是可以的

1.3.4 sql预编译

  1. SQL预编译是一种将SQL语句和参数分开处理的技术。它的基本原理是将SQL语句中的参数部分使用占位符代替,然后将参数值与SQL语句分开传递给数据库执行。这样可以提高数据库的性能和安全性。
  2. 在SQL预编译中,首先将SQL语句发送给数据库进行预编译,数据库会对SQL语句进行语法分析和优化,并生成一个执行计划。然后,应用程序将参数值与占位符一起发送给数据库执行计划,数据库会将参数值填充到执行计划中的占位符位置,最后执行SQL语句。

通过使用SQL预编译,可以实现以下优势:

  • 提高性能:由于SQL语句只需要预编译一次,后续执行只需要传递参数值,减少了语法分析和优化的开销,提高了执行效率。
  • 防止SQL注入攻击:通过使用占位符,可以将参数值与SQL语句分开处理,避免了恶意用户通过参数注入恶意代码的风险。
  • 简化参数处理:应用程序只需要关注参数值的传递,而不需要担心参数的类型和转义处理,减少了开发的复杂性。

        通过这个案例演示,可以看到$符号和#符号在占位符语法上的区别。在实际使用中,应根据具体的需求和安全性考虑选择合适的占位符语法。一般来说,推荐使用#符号占位符,以提高安全性和防止SQL注入攻击。

二、resultMap和resultType的区别

        1️⃣ resultType 是一种简单的映射方式,它指定了查询结果的类型。通常情况下,resultType可以是Java的基本类型(如int、String等)或者自定义的Java类。当查询结果只有一个列时,可以使用resultType。

例如,考虑以下数据库表格"users":

+----+----------+-----------+
| id | username |  password |
+----+----------+-----------+
| 1  |  John    |  123456   |
| 2  |  Jane    |  abcdef   |
+----+----------+-----------+

如果我们想要查询id为1的用户的用户名,可以使用以下MyBatis配置:

<select id="getUserUsername" resultType="java.lang.String">
  SELECT username FROM users WHERE id = #{id}
</select>

        在这个例子中,我们使用了resultType="java.lang.String"来指定查询结果的类型为String。这样,MyBatis会将查询结果直接映射为一个String对象。

        2️⃣ resultMap 是一种更为灵活的映射方式,它允许我们定义复杂的映射规则。通过resultMap,我们可以将查询结果映射为一个自定义的Java对象,而不仅仅是基本类型。

例如,我们可以定义一个User类来表示数据库中的用户:

public class User {
  private Integer id;
  private String username;
  private String password;

  // 省略构造函数、getter和setter方法
}

然后,我们可以使用resultMap来将查询结果映射为User对象:

<resultMap id="userResultMap" type="com.entity.User">
  <id property="id" column="id" />
  <result property="username" column="username" />
  <result property="password" column="password" />
</resultMap>

<select id="getUser" resultMap="userResultMap">
  SELECT * FROM users WHERE id = #{id}
</select>

        在这个例子中,我们定义了一个名为"userResultMap"的resultMap,指定了User类作为映射的类型。然后,我们使用<id>和<result>标签来指定每个属性的映射规则。

        通过使用resultMap,MyBatis会将查询结果映射为一个User对象,其中id、username和password属性会被正确地填充。

总结:

         resultType是指定查询结果的数据类型。它可以是Java的基本数据类型、JavaBean或者其他自定义的数据类型。当查询结果只有一个字段时,可以使用resultType来指定结果的数据类型。

        resultMap是用于将查询结果映射到Java对象的规则集合。它定义了查询结果与Java对象之间的映射关系。resultMap可以指定多个映射规则,用于处理复杂的查询结果。它可以映射查询结果中的每个字段到Java对象的属性,也可以进行一些特殊的映射操作,如级联映射、关联映射等。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/915212.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

kali的一些使用和ms08-067、ms17-010漏洞

VM虚拟机-三种网络连接方式&#xff08;桥接、NAT、仅主机模式&#xff09; 虚拟机网络连接 一、Bridged&#xff08;桥接&#xff09; 二、NAT&#xff08;网络地址转换&#xff09; 三、Host-Only&#xff08;仅主机&#xff09; 在vmware软件中&#xff0c;选项栏的“编…

【工具】VirtualBox虚拟机安装Windows操作系统

前面的文章中介绍了VirtualBox虚拟机的安装,VirtualBox虚拟机中如何安装操作系统,是本文的重点,下面将进行详细介绍。 使用VirtualBox虚拟机安装Windows操作系统有很多好处,主要包括以下几点: 节省资源:通过虚拟化技术,一台物理计算机可以同时运行多个虚拟机,每个虚拟…

什么是网站SSL证书?

SSL证书&#xff0c;使用SSL/TLS协议在服务器与客户端加密传输数据&#xff0c;提供身份验证的一种数字证书。 如果您不知道SSL证书&#xff0c;它还有一些别的叫法&#xff1a; HTTPS证书&#xff08;SSL证书能将网站从HTTP明文连接升级为HTTPS加密连接&#xff09;&#xf…

【Redis从头学-8】Redis中的ZSet数据类型实战场景之用户积分榜

&#x1f9d1;‍&#x1f4bb;作者名称&#xff1a;DaenCode &#x1f3a4;作者简介&#xff1a;啥技术都喜欢捣鼓捣鼓&#xff0c;喜欢分享技术、经验、生活。 &#x1f60e;人生感悟&#xff1a;尝尽人生百味&#xff0c;方知世间冷暖。 &#x1f4d6;所属专栏&#xff1a;Re…

Day8.22 E. Unforgivable Curse (easyhard version)

文章目录 E1. Unforgivable Curse (easy version)E2. Unforgivable Curse (hard version) E1. Unforgivable Curse (easy version) Problem - 1800E1 - Codeforces 将s串转换成t串&#xff0c;每次能交换s串中下标绝对值差3或差4的字符 有点像bfs最小步数&#xff0c;但是字…

时序分解 | MATLAB实现基于SWD群体分解的信号分解分量可视化

时序分解 | MATLAB实现基于SWD群体分解的信号分解分量可视化 目录 时序分解 | MATLAB实现基于SWD群体分解的信号分解分量可视化效果一览基本介绍程序设计参考资料 效果一览 基本介绍 基于SWD群体分解的分量可视化&#xff0c;基于群体分解的信号分解技术&#xff0c;MATLAB程序…

软考高级系统架构设计师(二)计算机操作系统

【原文链接】软考高级系统架构设计师&#xff08;二&#xff09;计算机操作系统 2.1 进程管理 2.1.1 操作系统的三个重要作用 管理计算机中运行的程序和分配各种软硬件资源为用户提供友善的人机界面为应用程序的开发和运行提供一个高效的平台 2.1.2 操作系统的四个特征 并…

Android开发基础知识总结(四)简单控件(下)

一.按钮触控 最常见的按钮button类继承自Textview类。 需要注意的是&#xff0c;在Button中显示的单词默认全部大写 ~ public void onClick(View v){s1et1.getText().toString();//有一些小bug&#xff0c;好像变量必须声明在Onclick方法内部才有效&#xff1f;&#xff1f;&am…

数据结构-----树的易错点

1.树的度和m叉树 •度为m的树&#xff08;度表示该结点有多少个孩子&#xff08;分支&#xff09;&#xff09; 任意结点的度<m(最多m个孩子) 至少又一个结点度m(有m个孩子) 一定是非空树&#xff0c;至少有m1个结点 •m叉树 任意结点的度<m(最多有m个孩子) 允许所…

Shell 编程快速入门 之 数学计算和函数基础

目录 1. 求两数之和 整数之和 浮点数之和 2. 计算1-100的和 for...in C风格for循环 while...do until...do while和until的区别 关系运算符 break与continue的区别 3. shell函数基础知识 函数定义 函数名 函数体 参数 返回值 return返回值的含义 return与…

2023大数据专业建设解决方案

打造产教融合的就业育人综合服务平台。 随着大数据产业链与技术链的逐步成熟&#xff0c;整体人工智能岗位将从原来的以算法人才为主&#xff0c;开始转向以应用型人才与数字 蓝领人才为主&#xff0c;形成金字塔型人才结构。应用型本科与职业院校的学生也将逐渐在人工智能领域…

Docker(一) 安装Docker

一、安装 安装前置条件 yum install -y yum-utils device-mapper-persistent-data lvm2 更换数据源 yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo 1、指定版本安装 yum list docker-ce --showduplicates | sort -r yum …

深入浅出理解卡尔曼滤波

重要说明&#xff1a;本文从网上资料整理而来&#xff0c;仅记录博主学习相关知识点的过程&#xff0c;侵删。 一、参考资料 我所理解的卡尔曼滤波 图说卡尔曼滤波&#xff0c;一份通俗易懂的教程 卡尔曼滤波简单分析 How a Kalman filter works, in pictures 说说卡尔曼滤波…

Java【手撕双指针】LeetCode 611. “有效三角形个数“, 图文详解思路分析 + 代码

文章目录 前言一、有效三角形个数1, 题目2, 思路分析1, 从左往右 or 从右往左?3, 代码展示 前言 各位读者好, 我是小陈, 这是我的个人主页, 希望我的专栏能够帮助到你: &#x1f4d5; JavaSE基础: 基础语法, 类和对象, 封装继承多态, 接口, 综合小练习图书管理系统等 &#x1…

一文了解Gin对Cookie的支持z

1. 引言 本文将从Web应用程序处理请求时需要用户信息&#xff0c;同时HTTP又是无状态协议这个矛盾点出发。从该问题出发&#xff0c;简单描述了解决该问题的Token 机制&#xff0c;进而引出Cookie的实现方案。 基于此我们将详细描述Cookie的规范&#xff0c;然后详细描述具体…

UE4如何连接dmx---摇头矩阵灯具的创建

UE4如何连接dmx---摇头矩阵灯具的创建 开始创建库&#xff01; 然后我们开始创建多少个灯珠&#xff08;注意了&#xff1a;这是矩阵灯&#xff0c;是看灯珠的&#xff09; 那么这里我们创建6X6灯珠 下面设置灯珠的属性&#xff0c;灯珠有什么属性呢&#xff0c;只有颜色属性&…

高忆管理:沪指震荡跌0.24%,医药、酿酒等板块走低,数据要素概念逆市活跃

22日早盘&#xff0c;两市股指高开低走&#xff0c;沪指盘中冲高回落&#xff0c;创业板指走势疲弱&#xff1b;北向资金净卖出超40亿元。 到午间收盘&#xff0c;沪指跌0.24%报3085.48点&#xff0c;深成指跌0.73%&#xff0c;创业板指跌1.3%&#xff1b;两市合计成交4510亿元…

Python 自定义装饰器与上下文管理

1、定义装饰器实现计算函数运行时间 # 自定义装饰器 def compute_time(func):def compute(*args, **kwargs):st time.time()result func(*args, **kwargs)et time.time()print(消费时间 %.6f s % (et - st))return resultreturn compute# 使用 compute_time def work(work_i…

(2018,解释可视化)GAN 解剖:可视化和理解生成对抗网络

GAN dissection: Visualizing and understanding generative adversarial networks 公众号&#xff1a;EDPJ 目录 0. 摘要 1. 简介 2. 相关工作 3. 方法 3.1 通过解剖表征单元 3.2 使用干预措施衡量因果关系 4. 结果 4.1 跨数据集、层和模型的单位比较 4.2 诊断和改…

VMware 使用U盘进入PE系统,下划线光标闪烁

一、前言 vmware虚拟机各种原因崩溃&#xff0c;然后又没有快照&#xff0c;怎么办&#xff1f; 或者 密码忘记了无法开机&#xff0c;这时候就想到使用PE了。 二、分析 但是使用U盘进入PE的时候&#xff0c;遇到了各种问题&#xff1a; 加载U盘修改启动顺序启动后出现下划线…