Mybatis动态SQL

在mybtis中动态sql主要用到的几个节点元素有:

1、if
2、choose(when, otherwise)
3、trim(where, if)
4、foreach

if的用法

  • 用法: if的用法较为简单,对一些条件做出判断,条件成立则执行,不成立则跳过。
  • 例子 当我们数据字段较多时,这是就会出现许多搜索条件,但在搜索时并不是所有的搜索条件,因此在写sql语句时就需要我们判断某些条件是否为空,如果为空就不执行该字段的查询。
<select id="queryStudentsByLikesAdmin" parameterType="map" resultType="map">
        SELECT student.no,student.name,student.gender,direction.name direction,profession.name profession,classes.name
        classesName
        FROM t_student student
        LEFT JOIN (SELECT id, name FROM t_direction) direction ON direction.id = student.direction_id

        LEFT JOIN (SELECT id,name FROM t_profession) profession ON profession.id = student.profession_id
        LEFT JOIN (SELECT id,name FROM t_classes) classes ON classes.id = student.classes_id

        <where>

            <if test="level!=''">
                and student.level = ${level}
            </if>
            and student.no LIKE #{studentNo}
            <if test="directionId!=''">
                and direction_id =#{directionId}
            </if>
            <if test="professionId!=''">
                AND profession.id = #{professionId}
            </if>
            <if test="classesId!=''">
                AND student.classes_id = #{classesId}
            </if>
            and student.name

            LIKE #{name}
        </where>
    </select>

choose(when, otherwise)的用法

  • 用法:choose when 主要在多个条件的情况下只满足其中一个条件的应用场景中使用,例如这里就构建一个query条件,分别传递id,name与createTime。假设我们查询Visitor表时,如果VisitorId有值则,使用Id查询,如果VisitorName有值则采用VisitName查询
  • 例子:
 <!-- 满足其中一个条件时候用choose when操作 -->
  <select id="getListChooseWhenDemo" resultMap="visitorRs"
    parameterType="BasicQueryArgs">
    <include refid="getListSqlConditions" />
    <where>
      <if test="queryStatus>0">
        status=#{queryStatus}
      </if>
      <choose>
        <when test="queryId!=0">
          and id=#{queryId}
        </when>
        <when test="queryName!=null">
          and name like #{queryName}
        </when>
        <otherwise>
          and createTime>= #{queryTime}
        </otherwise>
      </choose>
    </where>
  </select>
  • 在这里说一下<include>的用法,在mybatis中<sql>用来封装SQL语句, <include>来调用。简单例子:
//<sql>封装sql语句
<sql id="select">
    select * from T_name
</sql>
<sql id="desc">
    order by T_name.name DESC
</sql>

//<include>调用封装好的sql语句
<select id="find" resultType="*">
    <include refid="select" />
    <include refid="desc" />
</select>
  • 上面这段代码的意思就是查询T_name表中的全部信息,然后按照字段"name"进行排序。

where if (trim)的用法

  • where关键词的好处是在于,如果有相应的过滤条件的话,它知道在适当的时候插入where关键词。而且它也知道在何时该去掉相应的AND与OR的连接符
  • 例子
<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>
</select>

不会因为所有条件不满足变为

<select id="findActiveBlogLike" resultType="Blog">
 SELECT * FROM BLOG
 WHERE
</select>

或者因为没有满足第一个条件,单单满足后面的条件变成

<select id="findActiveBlogLike" resultType="Blog">
  SELECT * FROM BLOG
  WHERE
  AND title like ‘someTitle'
</select>
  • set trim和上面的where一样,set和trim也是智能标记
  • 例子
    <update id="updateUserSet" parameterType="User">
        update User
        <set>
            <if test="userName != null">userName=#{userName},</if>
            <if test="password != null">password=#{password},</if>
        </set>
        where id=#{id}
    </update>

如果两个条件都不为空,那么实际执行的sql语句为:

update User SET userName=?, password=? where id=?

set 自动识别并把sql语句中第二个逗号去掉的。

  • trim标识为格式化标识,可以与其他标识完成where和set的功能
    prefix 前缀增加 suffix 后缀增加 prefixOverrides 自动判断前置 suffixOverrides 自动判断后置
  <update id="updateUserTrim" parameterType="User">
     UPDATE User 
     <trim prefix="SET" suffixOverrides="," suffix="WHERE id = #{id}" >  
        <if test="userName != null and userName != '' ">  
                userName = #{userName},
         </if>
         <if test="password != null and password != '' ">  
                password=#{password},
         </if>  
     </trim>

与上面的set语句对比,prefix="SET" 是为SQL语句设置前缀,suffixOverrides是自动判断后缀 "," suffix="WHERE id = #{id}" 是自动在加上后缀。
如果password和userName都有值,则该条sql语句为:

UPDATE User SET userName = ?, password=? WHERE id = ? 

foreach的用法

foreach元素的属性主要有 item,index,collection,open,separator,close。

item

循环体中的具体对象。支持属性的点路径访问,如
item.age,item.info.details。 具体说明:在list和数组中是其中的对象,在map中是value。 该参数为必选。

collection

要做foreach的对象,作为入参时,List<?>对象默认用list代替作为键,数组对象有array代替作为键,Map对象用map代替作为键。 当然在作为入参时可以使用@Param("keyName")来设置键,设置keyName后,list,array,map将会失效。 除了入参这种情况外,还有一种作为参数对象的某个字段的时候。举个例子: 如果User有属性List ids。入参是User对象,那么这个collection = "ids" 如果User有属性Ids ids;其中Ids是个对象,Ids有个属性List id;入参是User对象,那么collection = "ids.id" 上面只是举例,具体collection等于什么,就看你想对那个元素做循环。 该参数为必选。

separator

元素之间的分隔符,例如在in()的时候,separator=","会自动在元素中间用“,“隔开,避免手动输入逗号导致sql错误,如in(1,2,)这样。该参数可选。

index

在list和数组中,index是元素的序号,在map中,index是元素的key,该参数可选。

open

foreach代码的开始符号,一般是(和close=")"合用。常用在in(),values()时。该参数可选。

close

foreach代码的关闭符号,一般是)和open="("合用。常用在in(),values()时。该参数可选。

需要注意一下collection不同情况下的用法

  1. 如果传入的是单参数且参数类型是一个List的时候,collection属性值为list
  2. 如果传入的是单参数且参数类型是一个array数组的时候,collection的属性值为array
  3. 如果传入的参数是多个的时候,我们就需要把它们封装成一个Map了,当然单参数也可

相关案例:

<select id="countByUserList" resultType="_int" parameterType="list">
select count(*) from users
  <where>
    id in
    <foreach item="item" collection="list" separator="," open="(" close=")" index="">
      #{item.id, jdbcType=NUMERIC}
    </foreach>
  </where>
</select>

![Uploading fc7388015ca53d2bbc8d4309f8527919_785719.jpg . . .]

上面的sql语句等价与

select count(*) from users WHERE id in ( ? , ? ) 

传入map类型的参数时:

<insert id="ins_string_string">
        insert into string_string (key, value) values
        <foreach item="item" index="key" collection="map"
            open="" separator="," close="">(#{key}, #{item})</foreach>
</insert>

表中需要两个值,正好和K,V对应,因而map中的一个K,V就对应一条数据,如果map中有多个K,V,就会保存多个结果
对应的sql语句为:

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

推荐阅读更多精彩内容