MyBatis的强大特性--动态SQL

news2024/9/22 11:31:38

目录

前言 

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" useGeneratedKey
            s="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_time
        from 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.coloradmin.cn/o/1273036.html

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

相关文章

【linux防火墙】设置开启路由转发,SNAT和DNAT转换原理及应用实操,添加自定义链归类iptables规则

目录 一、关于iptables规则的保存 1.1持久保存规则 1.2加载规则 1.3开机自动加载规则 1.4使用iptables-service软件来进行规则的保存和加载&#xff08;不建议使用&#xff09; 二、SNAT和DNAT的原理和应用 SNAT的原理与应用&#xff1a; DNAT的原理和应用&#xff1a; …

MySQL之 InnoDB逻辑存储结构

InnoDB逻辑存储结构 InnoDB将所有数据都存放在表空间中&#xff0c;表空间又由段&#xff08;segment&#xff09;、区&#xff08;extent&#xff09;、页&#xff08;page&#xff09;组成。InnoDB存储引擎的逻辑存储结构大致如下图。下面我们就一个个来看看。 页&#xff08…

【Qt绘图】之绘制坦克

使用绘图事件&#xff0c;绘制坦克。 效果 效果很逼真&#xff0c;想象力&#xff0c;有没有。 示例 代码像诗一样优雅&#xff0c;有没有。 包含头文件 #include <QApplication> #include <QWidget> #include <QPainter>绘制坦克类 class TankWidge…

机器人RL数据集探索

机器人RL数据集探索 相关资料汇总 相关资料汇总

hutool的bug之 DateUtil.endOfDay(DateUtil.date())

hutool 工具类DateUtil 使用时谨慎 DateUtil.endOfDay 得到的时间保存到数据时会增加一秒 首先比较下时间的long值&#xff1a; 这样就很明显的看出来&#xff0c;hutool工具类的date是毫秒位多了.999,保存到mysql 的时候&#xff0c;MySQL数据库对于毫秒大于500的数据进行…

SPI学习

SPI介绍 SPI&#xff1a;串行外设设备接口&#xff08;Serial Peripheral Interface&#xff09;&#xff0c;是一种高速的&#xff0c;全双工&#xff0c;同步通信总线。 全双工&#xff1a;同一时刻&#xff0c;能同时接收数据和发送数据。 半双工&#xff1a;同一时刻&am…

树与二叉树堆:经典OJ题集

目录 查找值为x的结点&#xff1a; 思路分析&#xff1a; 单值二叉树&#xff1a; 示例&#xff1a; 思路分析&#xff1a; 相同的树&#xff1a; 示例&#xff1a; 思路分析&#xff1a; 二叉树的前序遍历&#xff1a;——使用前序遍历把结点元素放入数组中 题…

二分算法(整数二分、浮点数二分)

文章目录 二分一、整数二分&#xff08;一&#xff09;整数二分思路&#xff08;二&#xff09;整数二分算法模板1.左查找&#xff08;寻找左侧边界&#xff09;2.右查找&#xff08;寻找右侧边界&#xff09;3.总模板 &#xff08;三&#xff09;题目&#xff1a;数的范围 二、…

算法通关村第五关—Hash基础知识(青铜)

Hash基础 一、Hash的概念和基本特征 哈希(Hash)也称为散列&#xff0c;就是把任意长度的输入&#xff0c;通过散列算法&#xff0c;变换成固定长度的输出&#xff0c;这个输出值就是散列值。很多人可能想不明白&#xff0c;这里的映射到底是啥意思&#xff0c;为啥访问的时间…

【brpc学习实践】ParallelChannel的使用与并行请求

概览 ParallelChannel (有时被称为“pchan”)同时访问其包含的sub channel,并合并它们的结果。用户可通过CallMapper修改请求,通过ResponseMerger合并结果。ParallelChannel看起来就像是一个Channel: 支持同步和异步访问。 发起异步操作后可以立刻删除。 可以取消。 支持超…

Vue生命周期:组件的生命之旅

&#x1f343;引言 在Vue.js中&#xff0c;每个组件都有其独特的生命周期。这个生命周期指的是组件从创建到销毁的一系列过程。了解并正确使用Vue的生命周期钩子&#xff0c;对于优化组件性能、管理组件状态以及实现特定功能至关重要。本文将详细介绍Vue的生命周期及其各个阶段…

mysql mybatis分页查询 大数据量 非常慢

查阅了很多博客和资料&#xff0c;这篇文章以思路为准&#xff0c;详细代码不细说&#xff0c;都是非常简单的方法&#xff0c;一看就明白。具体实现稍微百度一下就能出来。仅供参考。 如题&#xff1a;单表数据已经达到4千万条数据&#xff0c;通过mybatis的分页查询效率非常低…

如何提高销售技巧,增加客户的成交率?

如何提高销售技巧&#xff0c;增加客户的成交率&#xff1f; 在如今的市场环境中&#xff0c;销售技巧的高低往往决定了你是否能够成功地打动客户的心。想要提高销售业绩&#xff0c;除了产品质量和服务的保障&#xff0c;更需要你精进销售技巧&#xff0c;从而让客户愿意为你…

一种快速设计射频功放IC流程分享

No.1设计目标 在功率放大器PA中&#xff0c;输出级以及输出匹配决定了该功放的线性度、效率等关键性能指标&#xff0c;通常被优先考虑。在这个项目中输出级功放关键性能指标如下&#xff1a; 带宽&#xff1a;12-13 GHz OP1dB>13dBm 输出级 Power gain>5dB DE_P1dB&…

TCP解帧解码、并发送有效数据到FPGA

TCP解帧解码、并发送有效数据到FPGA 工程的功能&#xff1a;使用TCP协议接收到网络调试助手发来的指令&#xff0c;将指令进行解帧&#xff0c;提取出帧头、有限数据、帧尾&#xff1b;再将有效数据发送到FPGA端的BRAM上&#xff0c;实现信息传递。 参考&#xff1a;正点原子启…

基于springboot实现的在线考试系统

一、系统架构 前端&#xff1a;html | js | css | jquery | bootstrap 后端&#xff1a;springboot | springdata-jpa 环境&#xff1a;jdk1.7 | mysql | maven 二、 代码及数据库 三、功能介绍 01. 登录页 02. 管理员端-课程管理 03. 管理员端-班级管理 04. 管理员端-老师管理…

【CAN通信】CanIf模块详细介绍

目录 1.内容简介 2.CanIf详细设计 2.1 CanIf功能简介 2.2 一些关键概念 2.3依赖的上下层模块 2.4 功能详细设计 2.4.1 Hardware object handles 2.4.2 Static L-PDUs 2.4.3 Dynamic L-PDUs 2.4.4 Dynamic Transmit L-PDUs 2.4.5 Dynamic receive L-PDUs 2.4.6Physi…

微信小程序 - 开发版、体验版、正式版共享本地缓存

问题描述 最近突然发现一个大问题啊&#xff0c;小程序切换版本环境的时候发现数据被污染了&#xff0c;瞬间就怀疑不同环境版本的小程序本地缓存是否共享的&#xff1f;&#xff01; 果然是&#xff01; 解决方案 我们可能马上想到解决方案就是&#xff1a;给每一个环境版本…

不想花钱用aspera?这些免费的替代方案也同样快速哦

Aspera FASP是一款高速数据传输软件&#xff0c;被广泛应用于大文件的快速传输。然而&#xff0c;Aspera FASP并不便宜&#xff0c;对于一些小型企业或个人用户来说可能无法负担。因此&#xff0c;为了满足大家的需求&#xff0c;本文将介绍一些免费且同样快速的Aspera替代方案…

【meta】Scaling Speech Technology to 1,000+ Languages

nvidia-NeMo包含TTS的模型&#xff0c;开源数据 uroma转写工具介绍 uroman转写工具 N-to-M mapping 转写的规范&#xff0c;包含一些中文-拼音&#xff0c;拉丁文-读法的规则转换。字符串匹配规则下的查字典&#xff1b; 将字母对应到发音单元 转写规范 转写过程尽量做到可…