• (转)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 >
  • 相关阅读:
    springboot + driud连接池踩的坑____新手学习
    tomcat的安装
    无限极分类
    javascript ECMAscript 和node.js commonJs之间的关系
    变量名,引用和地址
    java中闭包的理解
    thinkphp 模型的curd
    thinkphp之migration 迁移文件的使用
    验证ArrayList是线程不安全的集合
    一个java小程序,盗取插入的U盘中的数据。
  • 原文地址:https://www.cnblogs.com/lixuwu/p/5915547.html
Copyright © 2020-2023  润新知