【MyBatis】学习纪要六:动态SQL

引言

动态SQL:Dynamic SQL。

本节我们来通过 MyBatis 的官方文档进行学习。

Description(描述)

官方描述如下:

One of the most powerful features of MyBatis has always been its Dynamic SQL capabilities. If you have any experience with JDBC or any similar framework, you understand how painful it is to conditionally concatenate strings of SQL together, making sure not to forget spaces or to omit a comma at the end of a list of columns. Dynamic SQL can be downright painful to deal with.

While working with Dynamic SQL will never be a party, MyBatis certainly improves the situation with a powerful Dynamic SQL language that can be used within any mapped SQL statement.

The Dynamic SQL elements should be familiar to anyone who has used JSTL or any similar XML based text processors. In previous versions of MyBatis, there were a lot of elements to know and understand. MyBatis 3 greatly improves upon this, and now there are less than half of those elements to work with. MyBatis employs powerful OGNL based expressions to eliminate most of the other elements:

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

My View

上面这段话,总结起来就三点:

  • MyBatis 在动态SQL这块很强大。

  • 你需要会 OGNL 表达式

  • if/choose/trim/foreach

OGNL

用法看这里:OGNL指南

另外,支持转义符,所以,看一下转义:

html转义符.png

if/where/trim/choose/foreach

  • if 表示 判断
  <if test="title != null">
    AND title like #{title}
  </if>
  • where

我们总会在if标签里写AND,那么当第一个不存在时就会出问题:
sql: ...WHERE AND ...

因此 where 是解决这个问题的

  <where>
    <if test="state != null">
         state = #{state}
    </if>
    <if test="title != null">
        AND title like #{title}
    </if>
    <if test="author != null and author.name != null">
        AND author_name like #{author.name}
    </if>
  </where>
  • trim

有人会说了,既然写在前面有问题,那可不可以写在后面呢?当然可以。

来看些 trim 的用法:

<trim prefix="WHERE" prefixOverrides="AND |OR ">
  ...
</trim>

-----

<trim prefix="SET" suffixOverrides=",">
  ...
</trim>

总结一下:
prefix:前面加什么
prefixOverrides:前面忽略掉什么
suffix:后缀
suffixOverrides:后面忽略掉什么

  • choose
  <choose>
    <when test="title != null">
      AND title like #{title}
    </when>
    <when test="author != null and author.name != null">
      AND author_name like #{author.name}
    </when>
    <otherwise>
      AND featured = 1
    </otherwise>
  </choose>
  • foreach

遍历一个集合。

collection:指定要遍历的集合:
list类型的参数会特殊处理封装在map中,map的key就叫list
item:将当前遍历出的元素赋值给指定的变量
separator:每个元素之间的分隔符
open:遍历出所有结果拼接一个开始的字符
close:遍历出所有结果拼接一个结束的字符
index:索引。遍历list的时候是index就是索引,item就是当前值

  WHERE ID in
  <foreach item="item" index="index" collection="list"
      open="(" separator="," close=")">
        #{item}
  </foreach>

set

    <update id="testUpdate">
        UPDATE
          user
        <set>
            <if test="user.name != null">name = #{user.name},</if>
            <if test="user.age != null and user.age >= 0">age = #{user.age}</if>
        </set>
        <where>
            <if test="user.id != null and user.id > 0">id = #{user.id}</if>
        </where>
    </update>

批量插入

  • 方法一:
    <insert id="testBatchInsert1">
        INSERT INTO
          user(name, age)
        VALUES
        <foreach collection="users" index="i" item="k" separator=",">
            (
            <if test="k.name != null">#{k.name}</if>
            ,
            <if test="k.age != null and k.age >= 0">#{k.age}</if>
            )
        </foreach>
    </insert>
  • 方法二:
    <insert id="testBatchInsert2">

        <foreach collection="users" index="i" item="k" separator=";">
            INSERT INTO
              user(name, age)
            VALUES(
            <if test="k.name != null">#{k.name}</if>
            ,
            <if test="k.age != null and k.age >= 0">#{k.age}</if>
            )
        </foreach>
    </insert>

注意

1、数据库的url应该如下配置:

spring.datasource.url=jdbc:mysql://localhost:3306/mybatis_demo?allowMultiQueries=true

2、此方法返回的影响行数不正确。

==> Preparing: INSERT INTO user(name, age) VALUES( ? , ? ) ; INSERT INTO user(name, age) VALUES( ? , ? )
==> Parameters: n3(String), 11(Integer), n4(String), 12(Integer)

<== Updates: 1
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@64fc097e]
rs num : 1

_parameter and _databaseId

_parameter,参数
_databaseId,当前数据库的Id

bind

关于数据绑定,MyBatis官网提供的例子如下:

<select id="selectBlogsLike" resultType="Blog">
  <bind name="pattern" value="'%' + _parameter.getTitle() + '%'" />
  SELECT * FROM BLOG
  WHERE title LIKE #{pattern}
</select>

引用sql

有些重复的,可以抽取出来

后记

测试代码:DynamicSQL-Demo

需要说明的是:为了保持测试风格,有些返回值类型不正确,导致测试报错,但这并不影响着一节的学习,因为你能够看到sql和结果。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 151,511评论 1 330
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 64,495评论 1 273
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 101,595评论 0 225
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 42,558评论 0 190
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 50,715评论 3 270
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 39,672评论 1 192
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,112评论 2 291
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 29,837评论 0 181
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 33,417评论 0 228
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 29,928评论 2 232
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,316评论 1 242
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 27,773评论 2 234
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,253评论 3 220
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 25,827评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,440评论 0 180
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 34,523评论 2 249
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 34,583评论 2 249

推荐阅读更多精彩内容

  • rljs by sennchi Timeline of History Part One The Cognitiv...
    sennchi阅读 7,068评论 0 10
  • 1. 简介 1.1 什么是 MyBatis ? MyBatis 是支持定制化 SQL、存储过程以及高级映射的优秀的...
    笨鸟慢飞阅读 5,246评论 0 4
  • 今天在简书浏览到一篇关于孩子数学启蒙的文章《幼儿学数学01》,对文章中的一些观点,我有点不认同。 1、 作者的观点...
    车成子阅读 1,418评论 4 3
  • 手贱又搜索了你的微博,不敢关注你,却一直把你放在搜索框里,或许关注了你也没有关系,你已经不再把我记起,即便微博就是...
    为你而写的名字阅读 341评论 0 0
  • 今天是《好好学习》第一天~坚持就是胜利!第一天的我收获多多! 1.关于知识改变命运 尽管重新理解了这句话~不是你有...
    学晶阅读 287评论 0 2