Mybatis动态SQL的使用方法

Mybatis的强大特性之一便是它的动态SQL。在实际开发中,数据库的查询比较复杂,需要在不同的逻辑中执行不同的SQL语句。我们往往要根据各种不同的场景拼接出不同的SQL语句,而Mybatis给我们提供了动态SQL,可以让我们根据具体的业务逻辑来拼接SQL语句。(Mybatis采用功能强大的基于OGNL的表达式来淘汰其他的大部分元素

if条件(简单的条件判断)

用户可以选择其中的任意某些字段或者都不选,这个时候我们的查询语句该怎么写呢。 其实很简单,我们只需要写一些动态的sql就可以实现这一功能。如下代码,只需要在拼接查询条件前,先用<if>是否为null,如果不为null,则执行代码时会把条件拼接在<where>

<select id="findActiveBlogLike" resultType="Blog">
    SELECT * FROM BLOG WHERE state = ‘ACTIVE’ 
  <if test="title != null">
    AND title like #{title}
  </if>
  <if test="author != null and author.name != null">
    AND author_name like #{author.name}
  </if>
</select>

现在回到“if”示例,这次我们将“ACTIVE = 1”也设置成动态的条件,看看会发生什么。

<select id="findActiveBlogLike"
     resultType="Blog">
  SELECT * FROM BLOG 
  <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>
</select>

where 元素只会在至少有一个子元素的条件返回 SQL 子句的情况下才去插入“WHERE”子句。而且,若语句的开头为“AND”或“OR”,where 元素也会将它们去除。

test属性

test的属性用于条件判断的语句中,它在Mybatis中广泛使用。它的作用相当于判断真假。在大部分场景中我们都是用它判断空和非空。有时候我们需要判断字符串、数字和枚举等。

choose(选择其中的一项)

有时我们不想应用到所有的条件语句,而只想从中择其一项。针对这种情况,MyBatis提供了 choose元素,它有点像 Java 中的switch 语句 我们来看一个简单的例子:

<select id="findActiveBlogLike"
     resultType="Blog">
  SELECT * FROM BLOG WHERE state = ‘ACTIVE’
  <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>
</select>

where(简化SQL语句中where条件判断)

在上面的案例中小伙伴们可能都发现了一个问题,就是我们在添加查询条件的时候,在查询条件之前都先添加了where 1=1,然后后面直接在这之后再追加and什么什么的,那么每次这样来写显然有点麻烦,有没有简单一点的方案呢?当然有,我们可以通过where元素简化SQL语句中的where条件,如下:

<select id="getUser3" resultMap="u">
        SELECT * FROM user2
        <where>
            <choose>
                <when test="id!=null">
                    AND id=#{id}
                </when>
                <when test="address!=null">
                    AND address=#{address}
                </when>
                <when test="username!=null">
                    AND user_name LIKE concat(#{username},'%')
                </when>
                <otherwise>
                    AND 10>id
                </otherwise>
            </choose>
        </where>
 </select>

这样,只有where元素中有条件成立,才会将where关键字组装到SQL中,这样就比前一种方式简单许多。

trim(替换和添加)

trimt元素就意味着我们需要去掉一些特殊的字符串,prefix代表的语句中的前缀,而prefixOverrides代表的是你需要去掉的那种字符串,我们可以将and替换为where,如下:

<select id="getUser4" resultMap="map">
        SELECT * FROM user2
        <!--这个语句中是把AND换成where,下面的写法基本与where是等效的-->
        <trim prefix="where" prefixOverrides="and">
            AND id=1
        </trim>
</select>

这个最终执行的sql是SELECT * FROM user2 where id=1

set(主要用于更新)

set是我们在更新表的时候使用的元素,通过set元素,我们可以逐字段的修改一条数据,如下:

<update id="update">
        UPDATE user2
        <set>
            <if test="username!=null">
                user_name=#{username},
            </if>
            <if test="password!=null">
                password=#{password}
            </if>
        </set>
        WHERE id=#{id}
</update>

在set元素中,如果遇到了逗号,系统会自动将之去除。

foreach(主要用于IN语句中)

foreach元素用来遍历集合,比如我想查询多个城市的人,我的sql语句可能是这样SELECT * FROM user2 WHERE address IN('西安','北京'),我在查询的时候可能只是传入了一个list集合,该集合中有西安和北京两个查询条件,那我如何将这个集合组装成一个sql语句呢?很简单,如下:

<!--foreach用于迭代数据的元素
    open表示开始的符号
    close表示结束符号
    seprator表示元素间的分隔符
    items表示迭代的数组
-->
<select id="getUserInCities" resultMap="BaseResultMap">
        SELECT * FROM user2
        WHERE address IN
        <foreach collection="cities" index="index" open="(" separator="," close=")" item="city">
            #{city}
        </foreach>
 </select>

collection表示传入的参数中集合的名称,index表示是当前元素在集合中的下标,openclose则表示如何将集合中的数据包装起来,separator表示分隔符,item则表示循环时的当前元素。这样一段配置最终组合成的sql就是SELECT * FROM user2 WHERE address IN('西安','北京')

注意 你可以将任何可迭代对象(如 List、Set 等)、Map 对象或者数组对象传递给*foreach*作为集合参数。当使用可迭代对象或者数组时,index 是当前迭代的次数,item 的值是本次迭代获取的元素。当使用 Map 对象(或者 Map.Entry 对象的集合)时,index 是键,item 是值

bind(预定义变量)

使用bind元素我们可以预先定义一些变量,然后在查询语句中使用,如下:

<select id="getUserByName" resultMap="">
        <bind name="un" value="username+'%'"></bind>
            SELECT* FROM user2 WHERE user_name LIKE #{un}
</select>

OGNL(Object-Graph Navigation Language )表达式

Mybatis的动态SQL和${}形式的参数中都用到了OGNL表达式,所以我们有必要了解OGNL的简单用法。Mybatis常用的OGNL表达式如下:

OGNL表达式 含义
e1 or e2
e1 and e2
e1 == e2 或 e1 eq e2
e1 != e2 或 e1 neq e2
e1 lt e2(小于)
e1 lte e2(小于等于,gt(大于),gte(大于等于))
e1 + e2、e1*e2、e1/e2、e1-e2、e1%e2
!e 或 not e
e.method(args) 调用对象方法
e.property 对象属性值
e1[e2] 按索引取值(List、数组和)

参考资料

https://blog.csdn.net/u012702547

http://www.mybatis.org/mybatis-3/zh/dynamic-sql.html

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

推荐阅读更多精彩内容

  • 1. 简介 1.1 什么是 MyBatis ? MyBatis 是支持定制化 SQL、存储过程以及高级映射的优秀的...
    笨鸟慢飞阅读 5,398评论 0 4
  • MyBatis 动态SQL 内容 Mybatis动态SQL在XML中支持的几种标签: if chose trim、...
    lihongyan阅读 8,339评论 1 10
  • 书本近几年与我已渐行渐远,不是不喜欢看书,也不是不喜欢阅读,而是时间越来越多被电子设备占据。而不管是手机、IPA...
    鸿哲阅读 234评论 1 0
  • 收获满满的一个下午! 看到六六在BetterMe深圳营发的用思维导图做年度规划的沙龙活动,立刻报名,一是为了面...
    童童小瑾书阅读 973评论 0 1
  • 闲谈诗歌与生活· 田 秀 有人拿生活摆菜来说诗,其实,我看没有不妥的地方.不过,拿这种方式去解释诗与生活的关系,我...
    兴安居士阅读 268评论 0 2