MyBatis的强大特性--动态SQL

目录

前言 

if 

trim

where

set 

foreach


前言 

        动态 SQL 是 MyBatis 的强大特性之一。如果你使用过 JDBC 或其它类似的框架,你应该能理解根据不同条件拼接 SQL 语句有多痛苦,例如拼接时要确保不能忘记添加必要的空格,还要注意去掉列表最后一个列名的逗号。利用动态 SQL,可以彻底摆脱这种痛苦。

        例如在注册用户的时候, 提交的表单中肯定有非必填字段, 前端会将拿到的数据送给后端, 但是, 用户在提交的时候, 由于存在非必填字段, 于是用户提交的字段可能是变数, 可能是一个, 两个或者三个, 例如有下面三个字段

  • username
  • password
  • tele
  • age(非必填)
  • sex
  • .....

        除了age都为必填, 这个时候, 前端返回数据给后端, 然后使用sql将其存入数据库, 那么, 在插入的时候

insert into table(username, password, tele, sex, age) values(#{username},#{username}, #{tele}, #{sex}, #{age});

       上面是age传入的时候, 那么试想一下, 如果这个age如果用户没有选择填写呢, 那么insert语句中的age选项就应该被抹除

        使用动态 SQL 并非一件易事,但借助可用于任何 SQL 映射语句中的强大的动态 SQL 语言,MyBatis 显著地提升了这一特性的易用性。

        如果你之前用过 JSTL 或任何基于类 XML 语言的文本处理器,你对动态 SQL 元素可能会感觉似曾相识。在 MyBatis 之前的版本中,需要花时间了解大量的元素。借助功能强大的基于 OGNL 的表达式,MyBatis 3 替换了之前的大部分元素,大大精简了元素种类,现在要学习的元素种类比原来的一半还要少。

  • if
  • choose (when, otherwise)
  • trim (where, set)
  • foreach

if 

    <insert id="insert" parameterType="org.example.model.User" useGeneratedKeys="true" keyProperty="id">insert into user(username,password,nickname,<if test="sex != null">sex,</if>birthday,head) values (#{username},#{password},#{nickname},<if test="sex != null">#{sex},</if>#{birthday},#{head})</insert>

        if中有一个test属性, test是判断这个sex项是否存在的标准, 前端传过来的数据会被解析为java对象, 并将属性写入到对象中, 如果对象中的sex属性为空, 那么就代表用户没有传入这个字段, 于是就需要将这个项给抹除.

trim

        上面的情况是只有一个选填项, 但是如果所有的字段, 都可能是选填项, 那么就可以配合trim使用if来解决:

    <insert id="insert" parameterType="org.example.model.User" useGeneratedKeys="true" keyProperty="id">insert into user<trim prefix="(" suffix=")" suffixOverrides=","><if test="username != null">username,</if><if test="password != null">password,</if><if test="nickname != null">nickname,</if><if test="sex != null">sex,</if><if test="birthday != null">birthday,</if><if test="head != null">head,</if><if test="createTime != null">create_time,</if></trim><trim prefix="values (" suffix=")" suffixOverrides=","><if test="username != null">#{username},</if><if test="password != null">#{password},</if><if test="nickname != null">#{nickname},</if><if test="sex != null">#{sex},</if><if test="birthday != null">#{birthday},</if><if test="head != null">#{head},</if><if test="createTime != null">#{createTime},</if></trim></insert>

 

  • prefix : 表示整个trim语句块的开头
  • suffix : 表示整个trim语句块的结尾
  • prefixOverrides : 表示整个语句块要去除掉的前缀
  • suffixOverrides : 表示整个语句块中, 要去除掉的后缀, 这个后缀是不计suffix的. 例如trim语句块如下, 那么结束的时候就为 " .... .... head, create_time,)" ,呢么就会忽略 ')', 去除create_time后面的','
    <if test="head != null">
    head,
    </if>
    <if test="createTime != null">
    create_time,
    </if>

上面语句翻译过来就是

isnert into user(username, password, age, sex, ) values(#{username}, #{password}, #{age}, #{sex},)

 

        需要注意的是, 这里的sex可能为选填, 无论如何, 这个table_name后面的参数和values中的参数, 必定有以 ',' 结尾的内容, 但是这个在sql中是错误语句. 于是使用suffixOverrides将后缀','去除(不包括 suffix =')').

where

        传⼊的⽤户对象,根据属性做 where 条件查询,⽤户对象中属性不为 null 的,都为查询条件。如user.username 为 "a",则查询条件为 where username="a":
UserMapper 接⼝中新增条件查询⽅法:

List<User> selectByCondition(User user);

xml中新增查询语句:

    <select id="selectByCondition" parameterType="org.example.model.User" resultMap="BaseResultMap">select id, username, password, nickname, sex, birthday, head, create_timefrom user<where><if test="username != null">and username=#{username}</if><if test="password != null">and password=#{password}</if><if test="nickname != null">and nickname=#{nickname}</if><if test="sex != null">and sex=#{sex}</if><if test="birthday != null">and birthday=#{birthday}</if><if test="head != null">and head=#{head}</if><if test="createTime != null">and create_time=#{createTime}</if></where></select>

        注意: 这里的and一定要写到 column = #{column } 的前面, 也就是:

' and column = #{column } '

        where标签就会自动识别并去除多余的and. 

        当然, where也可以使用trim标签和if标签代替.

set 

        根据传⼊的⽤户对象属性来更新⽤户数据,可以使⽤<set>标签来指定动态内容
定义mapper接口:

int updateById(User user);

xml:

    <update id="updateById" parameterType="org.example.model.User">update user<set><if test="username != null">username=#{username},</if><if test="password != null">password=#{password},</if><if test="nickname != null">nickname=#{nickname},</if><if test="sex != null">sex=#{sex},</if><if test="birthday != null">birthday=#{birthday},</if><if test="head != null">head=#{head},</if><if test="createTime != null">create_time=#{createTime},</if></set>where id=#{id}</update>

        set会自动去掉末尾的 ','

foreach

        对集合进⾏遍历时可以使⽤该标签。<foreach>标签有如下属性:

  • collection:绑定⽅法参数中的集合,如 List,Set,Map或数组对象
  • item:遍历时的每⼀个对象
  • open:语句块开头的字符串
  • close:语句块结束的字符串
  • separator:每次遍历之间间隔的字符串

 示例:根据多个⽂章 id 来删除⽂章数据

ArticleMapper 中新增接⼝⽅法

int deleteByIds(List<Integer> ids);

        使用List接收, Integer为泛型, 传入的是一个Integer的list集合, 每一个Integer对象对应一个要被删除的文章(Article)

ArticleMapper.xml 中新增删除 sql:

<delete id="deleteByIds">delete from article where id in<foreach collection="list" item="item" open="(" close=")" separator=",">#{item}</foreach>
</delete>

in后面其实是可以使用一个多表查询的, 现在这里使用的foreach进行遍历.

  • Collection指明集合的类型
  • itme表示每个每一个对象

然后就遍历成了:

delete from article where id in  (item1, item2, item3 ..... )

这一个个item对象就是list中的Integer对象. 也就是对应的int类型, 与id的类型对应. 



 

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

计算机视觉算法——基于Transformer的目标检测(DN DETR / DINO / Sparser DETR / Lite DETR)

计算机视觉算法——基于Transformer的目标检测&#xff08;DN DETR / DINO&#xff09; 计算机视觉算法——基于Transformer的目标检测&#xff08;DN DETR / DINO&#xff09;1. DN DETR1.1 Stablize Hungarian Matching1.2 Denoising1.3 Attention Mask 2. DINO2.1 Contrasti…

语音信号处理:librosa

1 librosa介绍 Librosa是一个用于音频和音乐分析的Python库&#xff0c;专为音乐信息检索&#xff08;Music Information Retrieval&#xff0c;MIR&#xff09;社区设计。自从2015年首次发布以来&#xff0c;Librosa已成为音频分析和处理领域中最受欢迎的工具之一。它提供了一…

【数据结构】源码角度剖析PriorityQueue

目录 认识 Queue 认识 PriorityQueue PriorityQueue为什么要用二叉堆&#xff1f; PriorityQueue构造方法源码分析 PriorityQueue 的属性 构造方法 JDK1.8传入不可比较的对象 JDK17传入不可比较的对象 传入带有Collection接口的对象 instanceof 关键字 Offer方法分析…

[安洵杯 2019]easy_web

打开环境 img传参还有cmd img应该是base&#xff0c;先解码看看 3535352e706e67 这个好像是十六进制的&#xff0c;再解 访问一下看看&#xff0c;得到一张图片 尝试base解码&#xff0c;但是没有什么发现 再看看地址栏出现index.php,应该是要下载源码&#xff0c;但是还没有…

kafka集群环境部署

文章目录 1 Kafka集群2 搭建两台服务器2.1 zookeeper部署2.2 启动1号机器的broker2.3 启动2号机器的broker2.4 查看kafka集群2.5 测试集群 1 Kafka集群 2 搭建两台服务器 2.1 zookeeper部署 zookeeper先只部署一台&#xff0c;在1号机器&#xff08;192.168.11.59&#xff09;…

windows配置使用supervisor

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、使用步骤1.安装supervisor-win2.配置supervisord3.配置program4.启动supervisord.exe5.supervisorctl.exe管控 二、后台启动总结 前言 windows使用supervi…

基于Java+SpringBoot+Vue3+Uniapp+TypeScript(有视频教程)前后端分离的求职招聘小程序

博主介绍&#xff1a;✌全网粉丝5W&#xff0c;全栈开发工程师&#xff0c;从事多年软件开发&#xff0c;在大厂呆过。持有软件中级、六级等证书。可提供微服务项目搭建与毕业项目实战&#xff0c;博主也曾写过优秀论文&#xff0c;查重率极低&#xff0c;在这方面有丰富的经验…

python技术栈之单元测试中mock的使用

什么是mock&#xff1f; mock测试就是在测试过程中&#xff0c;对于某些不容易构造或者不容易获取的对象&#xff0c;用一个虚拟的对象来创建以便测试的测试方法。 mock的作用 特别是开发过程中上下游未完成的工序导致当前无法测试&#xff0c;需要虚拟某些特定对象以便测试…

[python装饰器]什么是装饰器@

作者&#xff1a;20岁爱吃必胜客&#xff08;坤制作人&#xff09;&#xff0c;近十年开发经验, 跨域学习者&#xff0c;目前于新西兰奥克兰大学攻读IT硕士学位。荣誉&#xff1a;阿里云博客专家认证、腾讯开发者社区优质创作者&#xff0c;在CTF省赛校赛多次取得好成绩。跨领域…

代码随想录算法训练营第30天|回溯总结 332. 重新安排行程

回溯是递归的副产品&#xff0c;只要有递归就会有回溯&#xff0c;所以回溯法也经常和二叉树遍历&#xff0c;深度优先搜索混在一起&#xff0c;因为这两种方式都是用了递归。 回溯法就是暴力搜索&#xff0c;并不是什么高效的算法&#xff0c;最多再剪枝一下。 回溯算法能解…

手把手教会你--办公软件--Word--持续更新

有什么问题&#xff0c;请尽情问博主&#xff0c;QQ群796141573 1.1 Word排版基础1 保存和命名Ⅰ自动保存 2 建立标准的编辑环境(1)显示编辑标记(2)打开标尺(3)打开导航窗格 3 高效的鼠标/键盘手势(1)连续选中内容--shift(2)跳选内容--ctrl(3)矩形选择内容--alt(4)回到文档开头…

半导体器件——MOS管

半导体器件是导电性介于良导电体与绝缘体之间&#xff0c;利用半导体材料特殊电特性来完成特定功能的电子器件&#xff0c;可用来产生、控制、接收、变换、放大信 号和进行能量转换。 场效应晶体管是依靠一块薄层半导体受横向电场影响而改变其电阻(简称场效应)&#xff0c;使具…