(转)mybatis:动态SQL

概述:在mybatis中,动态语句是个非常强大和灵活的功能,并且动态语句可以放在sql的任何地方,利用该功能,我们可以写出非常灵活的代码。在mybatis的动态语句中常常可能会用到以下几个运算和逻辑判断符:

1,"!=" : 表示不等于

2,"=":表示等于。注意是一个等号。

3,"and" : 逻辑与(小写)

4,"or" : 逻辑或(小写)

1 if元素

该元素是我们经常会用到的,常用语判断传入的某个参数是否为null或者为某个指定的值,例如下面的语句。

<select id=”selectUsers” parameterType=”int” resultType=”User”>
    select
       user_id as "id",
       user_name as "userName",
       hashed_password as "hashedPassword"
    from some_table
    <if test="id != null and id!=‘‘">
           where id = #{id}
    </if>
   </select>

该语句的意思是判断参数id是否不为null以及不为空字符串,如果是则查询指定id的记录,不然查询全部的记录。元素里面的test属性,顾名思义就是测试的意思,即测试指定的表达式是否成立。

ps:test后面指定的参数为传入的参数

2 choose、when和otherwise

这3个元素是组合起用的,表达一种 if..else..的意义。例如:

<select id=”selectUsers” parameterType=”int” resultType=”User”>
    select
       user_id as "id",
       user_name as "userName",
       hashed_password as "hashedPassword"
    from some_table
    <choose>
      <when test="id != null">
             where id = #{id}
      </when>
      <otherwise>
             where id = ‘123‘
      </otherwise>
   </select>

上面表达的意思是,如果参数id不为空,则查询指定id的记录,否则查询id为123的记录。

这里只列举了一个when,其实可以连续的添加多个,但是otherwise只能有一个。

3 trim、where、set

这3个元素主要功能就是帮助我们去除多余的关键字。where对应sql语句中的where关键字,set对应更新语句中的set关键字。下面列举一个例子,如下:

<select id="findActiveBlogLike"
  parameterType="Blog" 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 title like #{author.name}
         </if>
</select>  

如果第1个if和第2个if条件成立,则形成的SQL为:

SELECT * FROM BLOG WHERE state=#{state} AND title like #{title}

如果第2个if和第3个if条件成立,则形成的SQL为:

SELECT * FROM BLOG WHERE  AND title like #{title} AND title like #{author.name} 

明显第二条语句是错误的。如果让我们自己来考虑到各种可能,那么在面对复杂的动态语句的时候,将会是非常头痛的事情,为此,mybatis框架为我们提供了更好的解决办法,例句如下:

3.1 trim元素

该元素的目的就是却掉前后执行的内容,其表达式如下:

<trim prefix="" prefixOverrides="" suffix="" suffixOverrides="" ></trim>

prefixOverrides:表示在trim包含的sql语句中,要被覆写的前缀,可以用"|"或者"||"来分割,例如:

  <trim  prefixOverrides="and | or" ></trim>
            这里面的and和or不区分大小写。

prefix:与prefixOverrides搭配使用,它们俩总是同时出现。该属性表示由prefixOverrides指定的前缀要被覆写成的内容。例如:

<trim prefix="" prefixOverrides="and | or" ></trim>   //表示把第一个and或者or变为空
<trim prefix="where" prefixOverrides="and " ></trim>  //表示把第一个and变为where

suffixOverridessuffix和上面两个的规则是一样的,只是这两个是处理语句的最后,而上面两个是处理语句的最前。

把上面的例子改为下面的方式:

<select id="findActiveBlogLike"
  parameterType="Blog" resultType="Blog">
         SELECT * FROM BLOG
    <trim prefix="where" prefixOverrides="and | or">
         <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 title like #{author.name}
         </if>
</select>  

如果条件1和条件2成立,则形成的SQL为:

SELECT * FROM BLOG where state = #{state} AND title like #{title}

可以发现,虽然state前面没有and或者or,但是trim会为语句加上where。

如果条件2和条件3成立,则形成的SQL为:

SELECT * FROM BLOG WHERE title like #{title} AND title like #{author.name}

这时,会把trim元素中的SQL语句的前缀AND变为where。

上面的效果和下面是一样的:

<select id="findActiveBlogLike"
  parameterType="Blog" resultType="Blog">
         SELECT * FROM BLOG WHERE
    <trim prefix="" prefixOverrides="and | or">
         <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 title like #{author.name}
         </if>
</select>  

我们再加上对suffix的使用,如下:

<select id="findActiveBlogLike"
  parameterType="Blog" resultType="Blog">
         SELECT * FROM BLOG
    <trim prefix="where" prefixOverrides="and | or"  suffix="" suffixOverrides=",">
         <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 title like #{author.name} ,
         </if>
</select>  

这时,如果条件3成立,会除掉最后的逗号","。

trim元素非常灵活,可以中在任何的位置,但由于我们在实际的使用中,where语句的后面和set语句的后面是最容易要处理的,所以mybatis又特意为我们定义了where元素和set元素。

3.2 where元素

先举例如下:

<select id=”findActiveBlogLike”
     parameterType=”Blog” 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 title like #{author.name}
     </if>
</where>

如果第2个if才成立,那么where元素会去掉AND。

3.3 set元素

set元素会动态前置SET关键字,而且也会消除任意无关的逗号。

<update id="updateAuthorIfNecessary"
 parameterType="domain.blog.Author">
 update Author
 <set>
      <if test="username != null">username=#{username},</if>
      <if test="password != null">password=#{password},</if>
      <if test="email != null">email=#{email},</if>
      <if test="bio != null">bio=#{bio},</if>
 </set>
 where id=#{id}
</update>

4 foreach

foreach元素是非常强大的,它允许你指定一个集合,声明集合项和索引变量,它们可以用在元素体内。它也允许你指定开放和关闭的字符串,在迭代之间放置分隔符。这个元素是很智能的,它不会偶然地附加多余的分隔符。通常是构建在IN条件中的。比如:

<select id="selectPostIn" resultType="domain.blog.Post">
    SELECT *
    FROM POST P
    WHERE ID in
        <foreach item="item" index="index" collection="list"
                                            open="(" separator="," close=")">
                  #{item}
          </foreach>
</select>

注意:你可以传递一个List实例或者数组作为参数对象传给MyBatis。当你这么做的时候,MyBatis会自动将它包装在一个Map中,用名称作为键。List实例将会以“list”作为键,而数组实例将会以“array”作为键。

1, item="item":这里指定的是集合遍历的时候每个元素的名字,就好比为集合中的对象定义了一个名字,我们可以通过该名字来使用对象,这里的例子取名为“item”,我们可以随意的改名。如果这个名字指定的是一个对象,那么我们也可以这么使用:#{item.name},即访问对象中的name属性。

2,collection="list":如果我们传递的参数是个对象,然后是要遍历对象中的某个集合,那么我们可以这么使用:collection="param.list",即:传入的参数名为param,该对象里面有个名为list的集合属性。

5 使用foreach进行批插入

方法:

 insert into Author (username ,password ,email )
    values
    <foreach collection="list" item="item" index="index" separator="," >
        (#{item.username},#{item.password},#{item.email })
    </foreach>

6 insert语句中使用动态sql

下面是一个在项目开发中使用的实际例子

主要是对<sql id="InfoManageSet">中set标签的使用,其中包含直接插入的字段和需要判断的字段。主要通过判断来达到一条sql语句的复用!

    <!-- 将平台转发的实时贷记或借记业务入库-->
    <insert id="insertOneCreditOrDebit" parameterType="TransferParam" >
         insert  into trndetail <include refid="InfoManageSet" />
    </insert >

    <sql id="InfoManageSet">
         <set >
                 <!-- 支付业务头组件 -->
                 transtype = #{transtype},
                 subday = substr(#{subdate},7,2),
                 <if test="transno != null and transno !=‘‘">transno = #{transno},</if>
                 <if test="transno == null or transno ==‘‘">transno = SEQ_CENTER_PAY_TRN.NEXTVAL,</if>
                 subnode = #{subnode},
                 curtype = #{curtype},
                 trnmoney = #{trnmoney},
                 transcode = #{transcode},
                 acttrnmoney =#{trnmoney}-#{feemoney},
                 feemoney = #{feemoney},

                 <!-- 付款方信息组件 -->
                 payaccbankno = #{payaccbankno},
                 payaccno = #{payaccno},
                 accttype = #{accttype},
                 <if test="payaccname != null and payaccname !=‘‘">payaccname = #{payaccname},</if>
                 <if test="payaccaddr != null and payaccaddr !=‘‘">payaccaddr = #{payaccaddr},</if>
                 <!-- 收款方信息组件 -->
                 acpaccbankno = #{acpaccbankno},
                 acpaccno = #{acpaccno},
                 acpacctype =#{acpacctype},
                 acpaccname = #{acpaccname},
                 acpaccaddr = #{acpaccaddr},

                <!-- 附言和回执附言 -->
                 <if test="atcmemo != null and atcmemo !=‘‘">atcmemo = #{atcmemo},</if>
                 <if test="retatcmemo != null and retatcmemo !=‘‘">retatcmemo = #{retatcmemo},</if>

                 <!-- 针对104 业务报文要素进行相关处理-->
                 <if test="transtype ==‘104‘">
                 tranchannel = #{tranchannel},
                 paybankno = #{paybankno},
                 acpbankno = #{acpbankno},
                 sndnode = #{payaccbankno},
                 rcvnode = #{acpaccbankno},
                 <!-- 轧差信息组件 -->
                 <if test="setwrkdate != null and setwrkdate !=‘‘">setwrkdate = #{setwrkdate},</if>
                 <if test="netno != null and netno !=‘‘">netno = #{netno},</if>
                 <!-- 对账处理信息组件 -->
                 <if test="chkdate != null and chkdate !=‘‘">chkdate = #{chkdate},</if>
                <if test="chknetno != null and chknetno !=‘‘">chknetno = #{chknetno},</if>
                 </if>

                 <!-- 针对105 业务报文要素进行相关处理-->
                 <if test="transtype ==‘105‘">
                 tranchannel = #{tranchannel},
                 paybankno = #{paybankno},
                 acpbankno = #{acpbankno},
                 sndnode = #{acpaccbankno},
                 rcvnode = #{payaccbankno},
                 purtypecode = #{purtypecode},
                 applytypecode = #{applytypecode},
                 purnote = #{purnote},
                 token = #{token}
                 </if>

                 <!-- 默认字段 -->
                 wrkdate = #{wrkdate},
                 sysdtime = sysdate,
                 subdate = #{subdate},
                 pstatus = #{pstatus},
                 pdtime = #{pdtime},

                 srflag = #{srflag},
                 orderno = concat(#{subdate}, SEQ_CENTER_PAY_TRN.NEXTVAL),
                 returnedmoney = ‘0‘,
                 returnedfeemoney = ‘0‘,
                 orgchlcode = ‘01‘,
                 destchlcode = ‘01‘,
                 setflag = ‘0‘,
                 settype = ‘0‘,
                 interestflag = ‘0‘,
                 cancelflag = ‘0‘,
                 returnnum = ‘0‘,
                 trnreverseflag = ‘0‘,
                 trnbackflag = ‘0‘,
                 dbtrfundflag = ‘0‘,
                 plyfundflag = ‘0‘,
                 <if test="retcode != null and retcode !=‘‘">retcode = #{retcode},</if>
                <if test="retdesc != null and retdesc !=‘‘">retdesc = #{retdesc},</if>
                <if test="newtransno != null and newtransno !=‘‘">transno = #{newtransno},</if>
          </set>
    </sql >
时间: 2024-10-03 23:11:52

(转)mybatis:动态SQL的相关文章

MyBatis动态SQL小结

p.MsoNormal,li.MsoNormal,div.MsoNormal { margin: 0cm; margin-bottom: .0001pt; text-align: justify; font-size: 10.5pt; font-family: 等线 } .MsoChpDefault { font-family: 等线 } div.WordSection1 { } ol { margin-bottom: 0cm } ul { margin-bottom: 0cm } Mybati

MyBatis动态SQL————MyBatis动态SQL标签的用法

1.MyBatis动态SQL MyBatis 的强大特性之一便是它的动态 SQL,即拼接SQL字符串.如果你有使用 JDBC 或其他类似框架的经验,你就能体会到根据不同条件拼接 SQL 语句有多么痛苦.拼接的时候要确保不能忘了必要的空格,还要注意省掉列名列表最后的逗号.利用动态 SQL 这一特性可以彻底摆脱这种痛苦. 通常使用动态 SQL 不可能是独立的一部分,MyBatis 当然使用一种强大的动态 SQL 语言来改进这种情形,这种语言可以被用在任意的 SQL 映射语句中. 动态 SQL 元素和

mybatis实战教程(mybatis in action)之八:mybatis 动态sql语句

mybatis 的动态sql语句是基于OGNL表达式的.可以方便的在 sql 语句中实现某些逻辑. 总体说来mybatis 动态SQL 语句主要有以下几类:1. if 语句 (简单的条件判断)2. choose (when,otherwize) ,相当于java 语言中的 switch ,与 jstl 中的choose 很类似.3. trim (对包含的内容加上 prefix,或者 suffix 等,前缀,后缀)4. where (主要是用来简化sql语句中where条件判断的,能智能的处理 a

用Groovy模板写MyBatis动态SQL

MyBatis动态SQL简介 MyBatis有个强大的功能,动态SQL.有了这个功能,定义在Mapper里的SQL语句,就不必是静止不变的了,而是可以根据传入的参数,动态调整.下面是MyBatis官方文档里的一个if语句的例子: <select id="findActiveBlogWithTitleLike" resultType="Blog"> SELECT * FROM BLOG WHERE state = 'ACTIVE' <if test=

Mybatis 动态sql(转载)

原文地址:http://www.cnblogs.com/dongying/p/4092662.html 传统的使用JDBC的方法,相信大家在组合复杂的的SQL语句的时候,需要去拼接,稍不注意哪怕少了个空格,都会导致错误.Mybatis的动态SQL功能正是为了解决这种问题, 其通过 if, choose, when, otherwise, trim, where, set, foreach标签,可组合成非常灵活的SQL语句,从而提高开发人员的效率.下面就去感受Mybatis动态SQL的魅力吧: 1

mybatis 动态sql语句

mybatis 的动态sql语句是基于OGNL表达式的.可以方便的在 sql 语句中实现某些逻辑. 总体说来mybatis 动态SQL 语句主要有以下几类: 1. if 语句 (简单的条件判断) 2. choose (when,otherwize) ,相当于java 语言中的 switch ,与 jstl 中的choose 很类似. 3. trim (对包含的内容加上 prefix,或者 suffix 等,前缀,后缀) 4. where (主要是用来简化sql语句中where条件判断的,能智能的

mybatis 动态sql和参数

mybatis 动态sql 名词解析 OGNL表达式 OGNL,全称为Object-Graph Navigation Language,它是一个功能强大的表达式语言,用来获取和设置Java对象的属性,它旨在提供一个更高的更抽象的层次来对Java对象图进行导航. OGNL表达式的基本单位是"导航链",一般导航链由如下几个部分组成: 属性名称(property) 方法调用(method invoke) 数组元素 所有的OGNL表达式都基于当前对象的上下文来完成求值运算,链的前面部分的结果将

4.mybatis动态SQL拼接/取值/OGNL

4.mybatis动态SQL拼接/取值 一.mybatis框架的SQL拼接是采用OGNL表达式进行的,以下我会列出常用的取值方法. 图片来源:慕课网 1.1常用的取值方法: 1.2特殊的取值方法: mod为取余数

MyBatis动态SQL之一使用 if 标签和 choose标签

bootstrap react https://segmentfault.com/a/1190000010383464 xml 中 < 转义 to thi tha <if test="pricehigh!=null"> and price < #{pricehigh,jdbcType=INTEGER} </if> MyBatis动态SQL之一使用 if 标签和 choose标签 <select id="getItems" p

mybatis动态sql中的两个内置参数(_parameter和_databaseId)

<!-- mybatis动态sql的两个内置参数           不只是方法传递过来的参数可以被用来判断,取值       mybatis默认还有两个内置参数           _parameter:代表整个参数                                      单个参数:_parameter就是这个参数                                      多个参数:参数会被封装为一个map:_parameter就是代表这个map