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

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

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

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

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

1 if元素

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

  1. <select id=”selectUsers” parameterType=”int” resultType=”User”>
  2. select
  3. user_id as "id",
  4. user_name as "userName",
  5. hashed_password as "hashedPassword"
  6. from some_table
  7. <if test="id != null and id!=''">
  8. where id = #{id}
  9. </if>
  10. </select>

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

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

2 choose、when和otherwise

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

  1. <select id=”selectUsers” parameterType=”int” resultType=”User”>
  2. select
  3. user_id as "id",
  4. user_name as "userName",
  5. hashed_password as "hashedPassword"
  6. from some_table
  7. <choose>
  8. <when test="id != null">
  9. where id = #{id}
  10. </when>
  11. <otherwise>
  12. where id = '123'
  13. </otherwise>
  14. </select>

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

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

3 trim、where、set

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

  1. <select id="findActiveBlogLike"
  2. parameterType="Blog" resultType="Blog">
  3. SELECT * FROM BLOG
  4. WHERE
  5. <if test="state != null">
  6. state = #{state}
  7. </if>
  8. <if test="title != null">
  9. AND title like #{title}
  10. </if>
  11. <if test="author != null and author.name != null">
  12. AND title like #{author.name}
  13. </if>
  14. </select>

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

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

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

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

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

3.1 trim元素

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

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

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

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

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

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

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

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

  1. <select id="findActiveBlogLike"
  2. parameterType="Blog" resultType="Blog">
  3. SELECT * FROM BLOG
  4. <trim prefix="where" prefixOverrides="and | or">
  5. <if test="state != null">
  6. state = #{state}
  7. </if>
  8. <if test="title != null">
  9. AND title like #{title}
  10. </if>
  11. <if test="author != null and author.name != null">
  12. AND title like #{author.name}
  13. </if>
  14. </select>

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

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

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

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

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

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

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

  1. <select id="findActiveBlogLike"
  2. parameterType="Blog" resultType="Blog">
  3. SELECT * FROM BLOG WHERE
  4. <trim prefix="" prefixOverrides="and | or">
  5. <if test="state != null">
  6. state = #{state}
  7. </if>
  8. <if test="title != null">
  9. AND title like #{title}
  10. </if>
  11. <if test="author != null and author.name != null">
  12. AND title like #{author.name}
  13. </if>
  14. </select>

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

  1. <select id="findActiveBlogLike"
  2. parameterType="Blog" resultType="Blog">
  3. SELECT * FROM BLOG
  4. <trim prefix="where" prefixOverrides="and | or" suffix="" suffixOverrides=",">
  5. <if test="state != null">
  6. state = #{state}
  7. </if>
  8. <if test="title != null">
  9. AND title like #{title}
  10. </if>
  11. <if test="author != null and author.name != null">
  12. AND title like #{author.name} ,
  13. </if>
  14. </select>

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

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

3.2 where元素

先举例如下:

  1. <select id=”findActiveBlogLike”
  2. parameterType=”Blog” resultType=”Blog”>
  3. SELECT * FROM BLOG
  4. <where>
  5. <if test=”state != null”>
  6. state = #{state}
  7. </if>
  8. <if test=”title != null”>
  9. AND title like #{title}
  10. </if>
  11. <if test=”author != null and author.name != null”>
  12. AND title like #{author.name}
  13. </if>
  14. </where>

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

3.3 set元素

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

  1. <update id="updateAuthorIfNecessary"
  2. parameterType="domain.blog.Author">
  3. update Author
  4. <set>
  5. <if test="username != null">username=#{username},</if>
  6. <if test="password != null">password=#{password},</if>
  7. <if test="email != null">email=#{email},</if>
  8. <if test="bio != null">bio=#{bio},</if>
  9. </set>
  10. where id=#{id}
  11. </update>

4 foreach

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

  1. <select id="selectPostIn" resultType="domain.blog.Post">
  2. SELECT *
  3. FROM POST P
  4. WHERE ID in
  5. <foreach item="item" index="index" collection="list"
  6. open="(" separator="," close=")">
  7. #{item}
  8. </foreach>
  9. </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进行批插入

方法:

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

6 insert语句中使用动态sql

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

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

  1. <!-- 将平台转发的实时贷记或借记业务入库-->
  2. <insert id="insertOneCreditOrDebit" parameterType="TransferParam" >
  3. insert into trndetail <include refid="InfoManageSet" />
  4. </insert >
  5.  
  6. <sql id="InfoManageSet">
  7. <set >
  8. <!-- 支付业务头组件 -->
  9. transtype = #{transtype},
  10. subday = substr(#{subdate},7,2),
  11. <if test="transno != null and transno !=''">transno = #{transno},</if>
  12. <if test="transno == null or transno ==''">transno = SEQ_CENTER_PAY_TRN.NEXTVAL,</if>
  13. subnode = #{subnode},
  14. curtype = #{curtype},
  15. trnmoney = #{trnmoney},
  16. transcode = #{transcode},
  17. acttrnmoney =#{trnmoney}-#{feemoney},
  18. feemoney = #{feemoney},
  19.  
  20. <!-- 付款方信息组件 -->
  21. payaccbankno = #{payaccbankno},
  22. payaccno = #{payaccno},
  23. accttype = #{accttype},
  24. <if test="payaccname != null and payaccname !=''">payaccname = #{payaccname},</if>
  25. <if test="payaccaddr != null and payaccaddr !=''">payaccaddr = #{payaccaddr},</if>
  26. <!-- 收款方信息组件 -->
  27. acpaccbankno = #{acpaccbankno},
  28. acpaccno = #{acpaccno},
  29. acpacctype =#{acpacctype},
  30. acpaccname = #{acpaccname},
  31. acpaccaddr = #{acpaccaddr},
  32.  
  33. <!-- 附言和回执附言 -->
  34. <if test="atcmemo != null and atcmemo !=''">atcmemo = #{atcmemo},</if>
  35. <if test="retatcmemo != null and retatcmemo !=''">retatcmemo = #{retatcmemo},</if>
  36.  
  37. <!-- 针对104 业务报文要素进行相关处理-->
  38. <if test="transtype =='104'">
  39. tranchannel = #{tranchannel},
  40. paybankno = #{paybankno},
  41. acpbankno = #{acpbankno},
  42. sndnode = #{payaccbankno},
  43. rcvnode = #{acpaccbankno},
  44. <!-- 轧差信息组件 -->
  45. <if test="setwrkdate != null and setwrkdate !=''">setwrkdate = #{setwrkdate},</if>
  46. <if test="netno != null and netno !=''">netno = #{netno},</if>
  47. <!-- 对账处理信息组件 -->
  48. <if test="chkdate != null and chkdate !=''">chkdate = #{chkdate},</if>
  49. <if test="chknetno != null and chknetno !=''">chknetno = #{chknetno},</if>
  50. </if>
  51.  
  52. <!-- 针对105 业务报文要素进行相关处理-->
  53. <if test="transtype =='105'">
  54. tranchannel = #{tranchannel},
  55. paybankno = #{paybankno},
  56. acpbankno = #{acpbankno},
  57. sndnode = #{acpaccbankno},
  58. rcvnode = #{payaccbankno},
  59. purtypecode = #{purtypecode},
  60. applytypecode = #{applytypecode},
  61. purnote = #{purnote},
  62. token = #{token}
  63. </if>
  64.  
  65. <!-- 默认字段 -->
  66. wrkdate = #{wrkdate},
  67. sysdtime = sysdate,
  68. subdate = #{subdate},
  69. pstatus = #{pstatus},
  70. pdtime = #{pdtime},
  71.  
  72. srflag = #{srflag},
  73. orderno = concat(#{subdate}, SEQ_CENTER_PAY_TRN.NEXTVAL),
  74. returnedmoney = '0',
  75. returnedfeemoney = '0',
  76. orgchlcode = '01',
  77. destchlcode = '01',
  78. setflag = '0',
  79. settype = '0',
  80. interestflag = '0',
  81. cancelflag = '0',
  82. returnnum = '0',
  83. trnreverseflag = '0',
  84. trnbackflag = '0',
  85. dbtrfundflag = '0',
  86. plyfundflag = '0',
  87. <if test="retcode != null and retcode !=''">retcode = #{retcode},</if>
  88. <if test="retdesc != null and retdesc !=''">retdesc = #{retdesc},</if>
  89. <if test="newtransno != null and newtransno !=''">transno = #{newtransno},</if>
  90. </set>
  91. </sql >

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

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

    mybatis 的动态sql语句是基于OGNL表达式的.可以方便的在 sql 语句中实现某些逻辑. 总体说来mybatis 动态SQL 语句主要有以下几类:1. if 语句 (简单的条件判断)2. c ...

  2. 9.mybatis动态SQL标签的用法

    mybatis动态SQL标签的用法   动态 SQL MyBatis 的强大特性之一便是它的动态 SQL.如果你有使用 JDBC 或其他类似框架的经验,你就能体会到根据不同条件拼接 SQL 语句有多么 ...

  3. 自己动手实现mybatis动态sql

    发现要坚持写博客真的是一件很困难的事情,各种原因都会导致顾不上博客.本来打算写自己动手实现orm,看看时间,还是先实现一个动态sql,下次有时间再补上orm完整的实现吧. 用过mybatis的人,估计 ...

  4. Mybatis动态SQL单一基础类型参数用if标签

    Mybatis动态SQL单一基础类型参数用if标签时,test中应该用 _parameter,如: 1 2 3 4 5 6 <select id="selectByName" ...

  5. 超全MyBatis动态SQL详解!( 看完SQL爽多了)

    MyBatis 令人喜欢的一大特性就是动态 SQL. 在使用 JDBC 的过程中, 根据条件进行 SQL 的拼接是很麻烦且很容易出错的. MyBatis 动态 SQL 的出现, 解决了这个麻烦. My ...

  6. Mybatis动态SQL简单了解 Mybatis简介(四)

    动态SQL概况 MyBatis 的强大特性之一便是它的动态 SQL 在Java开发中经常遇到条件判断,比如: if(x>0){ //执行一些逻辑........ }   Mybatis应用中,S ...

  7. mybatis原理分析学习记录,mybatis动态sql学习记录

    以下个人学习笔记,仅供参考,欢迎指正. MyBatis 是支持定制化 SQL.存储过程以及高级映射的持久层框架,其主要就完成2件事情: 封装JDBC操作 利用反射打通Java类与SQL语句之间的相互转 ...

  8. mybatis 动态sql和参数

    mybatis 动态sql 名词解析 OGNL表达式 OGNL,全称为Object-Graph Navigation Language,它是一个功能强大的表达式语言,用来获取和设置Java对象的属性, ...

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

    bootstrap react https://segmentfault.com/a/1190000010383464 xml 中 < 转义 to thi tha <if test=&qu ...

  10. MyBatis动态SQL(认真看看, 以后写SQL就爽多了)

    目录 0 一起来学习 mybatis 1 数据准备 2 if 标签 2.1 在 WHERE 条件中使用 if 标签 2.1.1 查询条件 2.1.2 动态 SQL 2.1.3 测试 2.2 在 UPD ...

随机推荐

  1. Mac下将ISO写入U盘镜像

    在Mac下面如果想做一个启动U盘,确实不如windows下那么方便,Windows下面有ultraiso+王涛,Mac下面测可以用下面的办法. 打开磁盘工具 插入U盘,并在磁盘工具里面找到U盘,把它卸 ...

  2. java小白进阶安卓第一天

  3. 机器学习:保序回归(IsotonicRegression):一种可以使资源利用率最大化的算法

    1.数学定义 保序回归是回归算法的一种,基本思想是:给定一个有限的实数集合,训练一个模型来最小化下列方程: 并且满足下列约束条件: 2.算法过程说明 从该序列的首元素往后观察,一旦出现乱序现象停止该轮 ...

  4. angular指令ng-class巧用

    什么是ng-class ng-class最大的妙用就是可以根据你的逻辑表达式.来添加或移除对应的class ng-class是angular.js里面内置的一个指令. 项目中,有时候,我们需要根据需求 ...

  5. Sql Server 事物

    事物的定义: 数据库的事物是原子性的,原子性的概念是指把一些事情当做一个单元来看待. 从数据库的角度看,它是指全部执行或者全部不执行的一条或者多条语句的最小组合:为了理解事务的概念,需要能够定义非常明 ...

  6. spring boot 入门操作(三)

    spring boot入门操作 devtools热部署 pom dependencies里添加依赖 <dependency> <groupId>org.springframew ...

  7. SICP-1.7-递归函数

    递归函数 函数内部直接或间接的调用函数自身 将复杂问题简单化 例子程序 def sum_digits(n): """Return the sum of the digit ...

  8. El表达式取map值

    map el表达取值 ${initMap['kehuList']}

  9. 保存Druid的监控记录

    继上篇帖子之后 , 公司又要求将Druid Monitor的监控信息保存起来 , 因为Druid的监控记录在是缓存的,重启之后无法找回,所以需要做持久化,定期把监控记录转存到日志文件中 研究了半天 , ...

  10. smarty获取变量的两种方式

    从上一篇随笔中,我们知道smarty可以通过assign()的方法注册变量,从而在前段读取变量:我们也可以从配置文件中获取变量,来具体看一下: 1.在configs文件夹中建一个test.conf文件 ...