什么是动态SQL

MyBatis的一个强大特性之一通常是它的动态SQL能力。如果你有使用JDBC或其他相似框架的经验,你就明白条件串联SQL字符串在一起是多么地痛苦,确保不能忘了空格或者在列表的最后的省略逗号,动态SQL可以彻底处理这种痛苦。

通常使用动态SQL不可能是独立的一部分,MyBatis当然使用一种强大的动态SQL语言来改进这种情形,这种语言可以被用在任意映射的SQL语句中。

动态SQL元素和使用JSTL或其它相似的基于XML的文本处理器相似,在MyBatis之前的版本中,有很多元素需要了解,MyBatis3大大地提升了它们,现在用不到原先一半的元素就能工作了,MyBatis采用功能强大的基于OGNL的表达式来消除其他元素。

OK,介绍就到这儿,下面来进入动态SQL的学习吧。

if

在动态SQL中所做的最通用的事情就是包含部分where子句的条件,比如:

<select id="selectInCondition" parameterType="student" resultType="student">select * from student where studentId > #{studentId}<if test="studentName != null">and studentName = #{studentName};</if>
</select>

具体实现不写了,那么如果我这么调用:

List<Student> list = StudentOperator.getInstance().selectInCondition(0, "Jack", 0, null);

查询的就是studentId>0且studentName="Jack"的所有学生信息,如果换一种调用方式

List<Student> list = StudentOperator.getInstance().selectInCondition(0, null, 0, null);

那么查询的就是studentId>0的所有学生信息。

多个where子句也是一样的,比如:

<select id="selectInCondition" parameterType="student" resultType="student"><![CDATA[select * from student where studentId > #{studentId}]]><if test="studentName != null and studentName != 'Jack' ">and studentName = #{studentName}</if><if test="studentAge != 0">and studentAge = #{studentAge};</if>
</select>

注意一下,能用"<![CDATA[ ... ]]>"尽量还是用,不过只包动态SQL外的内容。

另外,test里面可以判断字符串、整型、浮点型,大胆地写判断条件吧。如果属性是复合类型,则可以使用A.B的方式去获取复合类型中的属性来进行比较。

choose、when、otherwise

有时候我们不想应用所有的应用条件,相反我们想选择很多情况下的一种。和Java中的switch...case...类似,MyBasit提供choose元素。

上面的例子是两种if判断都可能存在,接下来使用choose、when、other做一些修改:

<select id="selectInCondition" parameterType="student" resultType="student"><![CDATA[select * from student where studentId > #{studentId}]]><choose><when test="studentName != null">and studentName = #{studentName};</when><when test="studentAge != 0">and studentAge = #{studentAge};</when><otherwise>or 1 = 1;</otherwise></choose>
</select>

两个when只能满足一个,都不满足则走other。还是注意一下这里的"<![CDATA[ ... ]]>",不可以包围整个语句。

trim、where、set

第一个例子已经示例了if的用法,但是这种用法有个缺陷----动态SQL外必须有where子句。

什么意思,因为很多时候我们需要where后面的子句都动态生成,而不是事先有一个where,这样就有问题,比如说:

<select id="selectInCondition" parameterType="student" resultType="student"><![CDATA[select * from student where]]><if test="studentName != null and studentName != 'Jack' ">and studentName = #{studentName}</if><if test="studentAge != 0">and studentAge = #{studentAge};</if>
</select>

如果所有条件都不匹配,那么生成的SQL语句将是:

select * from student where

这将导致查询失败。即使只满足一个查询条件还是有问题,比如满足studentName那个吧,生成的SQL语句将是:

select * from student where and studentName = #{studentName};

这个查询也会失败。

解决办法也有,一个讨巧的办法是用where 1 = 1的方式,即:

<select id="selectInCondition" parameterType="student" resultType="student"><![CDATA[select * from student where 1 = 1]]><if test="studentName != null and studentName != 'Jack' ">and studentName = #{studentName}</if><if test="studentAge != 0">and studentAge = #{studentAge};</if>
</select>

因为"1 = 1"永远满足,所以相当于给where加了一层true而已,此时动态SQL生成什么where判断条件就是什么。

另外一个解决办法是利用MyBatis中的一个简单处理方式,这在90%情况下都会有用而且。而在不能使用的地方,可以以自定义方式处理。加上一个简单的改变,所有的事情都会顺利进行:

<select id="selectInCondition" parameterType="student" resultType="student"><![CDATA[select * from student]]><where><if test="studentName != null and studentName != 'Jack' ">and studentName = #{studentName}</if><if test="studentAge != 0">and studentAge = #{studentAge};</if></where>
</select>

where元素知道如果由被包含的标记返回任意内容,就仅仅插入where。而且,如果以"and"或"or"开头的内容,那么就会跳过where不插入。

如果where元素没有做出你想要的,那么可以使用trim元素来自定义。比如,和where元素相等的trim元素是:

<trim prefix="WHERE" prefixOverrides="AND |OR ">
…
</trim>

即:

<select id="selectInCondition" parameterType="student" resultType="student">select * from student<trim prefix="WHERE" prefixOverrides="AND |OR "><if test="studentName != null and studentName != 'Jack' ">and studentName = #{studentName}</if><if test="studentAge != 0">and studentAge = #{studentAge};</if></trim>
</select>

特别要注意,prefixOverrides中的空白也是很重要的

最后一个小内容,和动态更新语句相似的解决方案是set。set元素可以被用于动态包含更新的列,而不包含不需要更新的。比如:

<update id="updateStudentAgeById" parameterType="Student"><!--update student set studentAge = #{studentAge} where studentId = #{studentId}; --><![CDATA[update student]]> <set><if test="studentAge != 0">studentAge = #{studentAge}</if></set>where studentId = #{studentId}
</update>

可以对比一下,注释掉的是原update语句,没有注释的是加入动态SQL之后的语句。

这里,set元素会动态前置set关键字,而且也会消除任意无关的逗号。如果你对和这里对等的trim元素好奇,它看起来是这样的:

<trim prefix="SET" prefixOverrides=",">
…
</trim>

这种时候我们附加一个后缀,同时也附加一个前缀。

foreach

另外一个动态SQL通用的必要操作时迭代一个集合,通常是构建在in条件中的。比如(上面的例子都是我在自己电脑上跑通过的例子,这个例子就直接复制MyBatis官方文档上的内容了):

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

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

原文:http://www.cnblogs.com/xrq730/p/5289638.html

转载于:https://www.cnblogs.com/flandre/p/6221478.html

MyBatis4:动态SQL相关推荐

  1. Mybatis入门:3(动态sql)

    动态sql语句 if标签 基本使用 一.在ProductDao接口中创建一个查询方法findByType import com.domain.Product;import java.util.List ...

  2. MyBatis动态SQL之 set 和 trim标记的使用示例

    2019独角兽企业重金招聘Python工程师标准>>> 和之前的where一样,set和trim也是智能标记 在之前的user.xml中添加 <update id=" ...

  3. Oracle基础 动态SQL语句

    一.静态SQL和动态SQL的概念. 1.静态SQL 静态SQL是我们常用的使用SQL语句的方式,就是编写PL/SQL时,SQL语句已经编写好了.因为静态SQL是在编写程序时就确定了,我们只能使用SQL ...

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

    点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试文章 来源:cnblogs.com/homejim/p/9909657. ...

  5. mybatis 注解 动态sql_Mybatis 的动态 SQL 语句

    Mybatis 的映射文件中,前面我们的 SQL 都是比较简单的,有些时候业务逻辑复杂时,我们的 SQL 是动态变 化的,此时在前面的学习中我们的 SQL 就不能满足要求了. 参考的官方文档,描述如下 ...

  6. java selectcommand_“对于不返回任何基表信息的 SelectCommand 不支持动态SQL生成”-奇怪的错误,不知道原因! | 学步园...

    OleDbCommandBuilder更新Access数据库中遇到的问题 部分代码如下: //AccountQuery.aspx.cs protected void FormView1_ItemUpd ...

  7. SQL Server-聚焦sp_executesql执行动态SQL查询性能真的比exec好?

    前言 之前我们已经讨论过动态SQL查询呢?这里为何再来探讨一番呢?因为其中还是存在一定问题,如标题所言,很多面试题也好或者有些博客也好都在说在执行动态SQL查询时sp_executesql的性能比ex ...

  8. mybatis入门篇(四):mybatis动态SQL

    2019独角兽企业重金招聘Python工程师标准>>> 这里提到的动态SQL用法都是基于mapper的xml配置文件的. 1.if 这个标签可以用于多条件查询,也可以用于新增/更新数 ...

  9. 在SQLMAP中使用动态SQL

    最近有几个同事和朋友询问如何在SQLMAP中"拼接字符串",因为有时候条件的数量不固定,条件参数类型也不固定,无法写出 @参数名 这样的SQL语句,也就是大家常说的"动态 ...

最新文章

  1. DeepMind Nando(原牛津大学教授)强化学习最新进展,含图文、公式和代码,附102页PPT下载...
  2. source insight设置tab键为4个空格
  3. 把运行在 Docker 容器内的 Microsoft SQL 服务器部署到 SAP Kyma 中
  4. P2766 最长不下降子序列问题(网络流)
  5. Delta3d组件以及消息机制
  6. 用Jenkins自动化搭建测试环境_入门试炼05
  7. 25 张图,1.4 w字!彻底搞懂分布式事务原理
  8. php7 setcookie无效_php COOKIE介绍和setcookie有时会在ie下失效问题
  9. 计算机术语hpp,HPP(计算机术语)_百度百科
  10. Matlab从入门到精通(六)--矩阵基本运算
  11. excel转pdf排版怎么不变
  12. 微信模拟地理位置_微信电脑版伪装地理位置的方法
  13. vue姓名动态输入三种方式、前端密码加密
  14. Netfilter学习之NAT类型动态配置(三)MASQUERADE内核空间的实现
  15. 游戏模型制作的注意事项——模型规范
  16. 2018的趋势与展望(下)——记罗振宇“时间的朋友2017”跨年演讲
  17. 360无线wifi路由器连接到服务器,360无线路由器怎么有线桥接设置
  18. 【个人提升】如何克服惰性
  19. Unity3d模型渲染灯光黑暗问题解决
  20. C# WinForm 文件夹选择控件 folderBrowserDialog 的应用实例

热门文章

  1. Catalyst 4000 6000配置经验谈(一)
  2. ASP.NET学习笔记 1
  3. java mybatis狂神说sql_狂神说SpringBoot09:整合MyBatis
  4. 计算机电容的作用,电容和电感的作用
  5. Xamarin ios C#苹果应用开发第二讲配置环境和编写代码
  6. scss安装_安装了这9个免费PS插件后,终于能正常时间下班了……
  7. sap事务代码_SAP事务码太多,记不住怎么办?
  8. CMU贺斌教授团队提出:冥想可以增强对脑机接口的控制
  9. 广州新房都智能成这样了???
  10. 用上强化学习和博弈论,EA开发的测试AI成精了