ibatis中使用安全的拼接语句,动态查询,ibatis比JDBC的优势之一,安全高效 
说明文字在注释中

一.引入

一个小例子
  <select id="selectAllProducts" parameterClass="Product" resultMap="ProductResult"> 
    select id,note from Product 
       <dynamic prepend="WHERE"> 
       <!-- isNotNull判断参数是否存在,Integer类型 --> 
            <isNotNull property="id"> 
                <!-- isGreaterThan判断参数是否大于compareValue,isGreaterEquals是大于等于 --> 
                <isGreaterThan prepend=" and " property="id" compareValue="0"> 
                id = #id# 
                </isGreaterThan> 
            </isNotNull> 
            <!-- isNotEmpty判断字串不为空,isEmpty可以判断字串为空 --> 
            <isNotEmpty prepend=" and " property="note"> 
            <!-- 模糊查询不能用#,#在是用prepareStatement的?插入参数,$是文本替换 --> 
            note like '%$note$%' 
            </isNotEmpty> 
        </dynamic> 
  </select> 
  
二.用Map传参数 或者用class传参
  
<select id="selectAllProducts" parameterClass="java.util.HashMap" resultMap="ProductResult"> 
    select id,note from Product 
       <dynamic prepend="WHERE"> 
       <!-- isPropertyAvailable判断属性是否有效 --> 
          <isPropertyAvailable property="id"> 
            <isNotNull property="id"> 
                <!-- isLessThan判断参数是否小于compareValue,isLessEquals是小于等于 --> 
                <isLessThan prepend=" and " property="id" compareValue="10"> 
                id = #id# 
                </isLessThan> 
            </isNotNull> 
          </isPropertyAvailable> 
        </dynamic> 
  </select> 
三.动态SQL的参数 
属性关键字 
含义

<isEqual> 
如果参数相等于值则查询条件有效。

<isNotEqual> 
如果参数不等于值则查询条件有效。

<isGreaterThan> 
如果参数大于值则查询条件有效。

<isGreaterEqual> 
如果参数等于值则查询条件有效。

<isLessEqual> 
如果参数小于值则查询条件有效。如下所示:

  <isLessEqual prepend = ”AND” property = ”age” compareValue = ”18” >

    ADOLESCENT = ‘TRUE’

  </isLessEqual>

<isPropertyAvailable> 
如果参数有使用则查询条件有效。

<isNotPropertyAvailable> 
如果参数没有使用则查询条件有效。

<isNull> 
如果参数为NULL则查询条件有效。

<isNotNull> 
如果参数不为NULL则查询条件有效。

<isEmpty> 
如果参数为空则查询条件有效。

<isNotEmpty> 
如果参数不为空则查询条件有效。参数的数据类型为Collection、String 时参数不为NULL或“”。如下所示:

<isNotEmpty prepend=”AND” property=”firstName” >

FIRST_NAME=#firstName#

</isNotEmpty>

<isParameterPresent> 
如果参数类不为NULL则查询条件有效。

<isNotParameterPresent> 
Checks to see if the parameter object is not present (null). Example Usage:

<isNotParameterPresent prepend=”AND”>

EMPLOYEE_TYPE = ‘DEFAULT’

</isNotParameterPresent>

四.复杂查询
在复杂查询过程中,我们常常需要根据用户的选择决定查询条件,这里发生变化的并不只是SQL 中的参数,包括Select 语句中所包括的字段和限定条件,都可能发生变化。典型情况,如在一个复杂的组合查询页面,我们必须根据用户的选择和输入决定查询的条件组合。

一个典型的页面如下:

对于这个组合查询页面,根据用户选择填写的内容,我们应为其生成不同的查询语句。如用户没有填写任何信息即提交查询请求,我们应该返回所有记录: 
Select * from t_user; 
如用户只在页面上填写了姓名“Erica”,我们应该生成类似: 
Select * from t_user where name like ‘%Erica%’ ;的SQL查询语句。 
如用户只在页面上填写了地址“Beijing”,我们应该生成类似: 
Select * from t_user where address like ‘%Beijing%”;的SQL。 
而如果用户同时填写了姓名和地址(”Erica”&’Beijing’),则我们应生成类似: 
Select * from t_user where name like ‘%Erica%’ and address like ‘%Beijing%”的SQL查询语句。

对于ibatis 这样需要预先指定SQL 语句的ORM 实现而言,传统的做法无非通过if-else 语句对输入参数加以判定,然后针对用户选择调用不同的statement 定义。对于上面这种简单的情况(两种查询条件的排列组合,共4 种情况)而言,statement 的重复定义工作已经让人不厌其烦,而对于动辄拥有七八个查询条件,乃至十几个查询条件 
的排列组合而言,琐碎反复的statement定义实在让人不堪承受。

考虑到这个问题,ibatis引入了动态映射机制,即在statement定义中,根据不同的 
查询参数,设定对应的SQL语句。 
还是以上面的示例为例: 
<select id="getUsers" 
parameterClass="user" 
resultMap="get-user-result"> 
select 
id, 
name, 
sex 
from t_user 
<dynamic prepend="WHERE"> 
<isNotEmpty prepend="AND" property="name"> 
(name like #name#) 
</isNotEmpty> 
<isNotEmpty prepend="AND" property="address"> 
(address like #address#) 
</isNotEmpty> 
</dynamic> 
</select> 
通过dynamic 节点,我们定义了一个动态的WHERE 子句。此WHERE 子句中将 
可能包含两个针对name 和address 字段的判断条件。而这两个字段是否加入检索取决于用户所提供的查询条件(字段是否为空[isNotEmpty])。 
对于一个典型的Web程序而言,我们通过HttpServletRequest获得表单中的字段名并将其设入查询参数,如:
user.setName(request.getParameter("name")); 
user.setAddress(request.getParameter("address")); 
sqlMap.queryForList("User.getUsers", user); 
在执行queryForList("User.getUsers", user)时,ibatis 即根据配置文 
件中设定的SQL动态生成规则,创建相应的SQL语句。 
上面的示例中,我们通过判定节点isNotEmpty,指定了关于name 和address 属 
性的动态规则: 
<isNotEmpty prepend="AND" property="name"> 
(name like #name#) 
</isNotEmpty> 
这个节点对应的语义是,如果参数类的"name"属性非空(isNotEmpty,即非空 
字符串””),则在生成的SQL Where字句中包括判定条件(name like #name#),其 
中#name#将以参数类的name属性值填充。 
Address属性的判定生成与name属性完全相同,这里就不再赘述。 
这样,我们通过在statement 定义中引入dynamic 节点,很简单的实现了SQL 判定子句的动态生成,对于复杂的组合查询而言,这将带来极大的便利。判定节点的定义可以非常灵活,我们甚至可以使用嵌套的判定节点来实现复杂的动态映射,如: 
<isNotEmpty prepend="AND" property="name"> 
( name=#name# 
<isNotEmpty prepend="AND" property="address"> 
address=#address# 
</isNotEmpty> 

</isNotEmpty> 
这段定义规定,只有用户提供了姓名信息时,才能结合地址数据进行查询(如果只提供地址数据,而将姓名信息忽略,将依然被视为全检索)。Dynamic节点和判定节点中的prepend属性,指明了本节点中定义的SQL子句在 
主体SQL中出现时的前缀。如:

<dynamic prepend="WHERE"> 
<isNotEmpty prepend="AND" property="name"> 
(name like #name#) 
</isNotEmpty> 
<isNotEmpty prepend="AND" property="address"> 
(address like #address#) 
</isNotEmpty> 
</dynamic>

假设"name"属性的值为“Erica”, "address"属性的值为“Beijing”,则会生成类似下面的SQL子句(实际运行期将生成带占位符的PreparedStatement,之后再为其填充数据):

WHERE (name like ‘Beijing’) AND (address like ‘Beijing’)

其中WHERE 之后的语句是在dynamic 节点中所定义,因此以dynamic 节点的prepend设置("WHERE")作为前缀,而其中的”AND”,实际上是address属性所对应的isNotEmpty节点的prepend设定,它引领了对应节点中定义的SQL子句。至于name属性对应的isNotEmpty节点,由于ibatis会自动判定是否需要追加prepend前缀,这里(name like #name#)是WHERE 子句中的第一个条件子句,无需AND 前缀,所以自动省略。 
七 .判定条件
判定节点并非仅限于isNotEmpty,ibatis中提供了丰富的判定定义功能。判定节点分两类:

Ø 一元判定 
一元判定是针对属性值本身的判定,如属性是否为NULL,是否为空值等。 
上面示例中isNotEmpty就是典型的一元判定。

一元判定节点有:

节点名 描述 
<isPropertyAvailable> 参数类中是否提供了此属性 
<isNotPropertyAvailable> 与<isPropertyAvailable>相反 
<isNull> 属性值是否为NULL 
<isNotNull> 与<isNull>相反 
<isEmpty> 如果属性为Collection或者String,其size是否<1,如果非以上两种类型,则通过String.valueOf(属性值) 
获得其String类型的值后,判断其size是否<1<isNotEmpty> 与<isEmpty>相反。

Ø 二元判定 
二元判定有两个判定参数,一是属性名,而是判定值,如 
<isGreaterThan prepend="AND" property="age" 
compareValue="18"> 
(age=#age#) 
</isGreaterThan> 
其中,property="age"指定了属性名”age”,compareValue=”18”指明了判定值为”18”。上面判定节点isGreaterThan 对应的语义是:如果age 属性大于18(compareValue),则在SQL中加入(age=#age#)条件。 
二元判定节点有: 
节点名 属性值与compareValues的关系 
<isEqual> 相等。 
<isNotEqual> 不等。 
<isGreaterThan> 大于 
<isGreaterEqual> 大于等于 
<isLessThan> 小于 
<isLessEqual> 小于等于

ibatis Dynamic总结(ibatis使用安全的拼接语句,动态查询)的更多相关文章

  1. ibatis 动态查询

    http://www.iteye.com/topic/393042最近做了很多动态的查询,尤其是排序,以及一些状态字段,所以就做了一个总的动态查询,以不变应万变,呵呵 ibatis 里面的sql代码: ...

  2. ibatis动态查询条件

    ibatis的调试相对困难,出错的时候主要依据是log4生成的log文件和出错提示,这方面要能比较熟练的看懂. 下面这个配置基本上包含了最复杂的功能:分页\搜索\排序\缓存\传值Hash表\返回has ...

  3. Java下拼接运行动态SQL语句

    mod=viewthread&tid=3039" target="_blank">Java拼接动态SQL的一般做法有       1.使用动态语句 非常多数 ...

  4. Java下拼接执行动态SQL语句(转)

    在实际业务中经常需要拼接动态SQL来完成复杂数据计算,网上各类技术论坛都有讨论,比如下面这些问题: http://bbs.csdn.net/topics/390876591 http://bbs.cs ...

  5. sql 针对拼接语句的优化

    在日常的开发中尽量少采用拼接语句,但针对多条件联合查询,并有多字段可以偏序的情况下,的确采用拼接语句要方便简单得多,单数据库会因为传入的参数不同而产生不同的计划数,计划数多了,对数据库影响很大. 为了 ...

  6. EF 6.x、EF Core实现dynamic动态查询和EF Core实现多个上下文实例池你了解多少?

    前言 很长一段时间没有写博客了,今天补上一篇吧,偶尔发现不太愿意写博客了,太耗费时间,不过还是在坚持当中,毕竟或许写出来的东西能帮到一些童鞋吧,接下来我们直奔主题.无论是在在EF 6.x还是EF Co ...

  7. jquery获取当前按钮、截取字符串、字符串拼接、动态循环添加元素

    截取字符串:字符串拼接:动态循环添加元素:获取当前按钮: {data : null, render: function(data, type, row ) { var loginName = $(&q ...

  8. EF 6.x实现dynamic动态查询

    利用SqlQuery实现动态查询 public static IEnumerable<dynamic> SqlQueryDynamic(this DbContext db, string ...

  9. Sql动态查询拼接字符串的优化

    Sql动态查询拼接字符串的优化 最原始的 直接写:string sql="select * from TestTables where 1=1";... 这样的代码效率很低的,这样 ...

随机推荐

  1. Spring 配置 事务的几种方式

    Spring配置文件中关于事务配置总是由三个组成部分,DataSource.TransactionManager和代理机制这三部分,无论是那种配置方法,一般变化的只是代理机制这块! 首先我创建了两个类 ...

  2. 高并发Web

    hadoop适合处理分布式集群系统,本身是支持高速并发海量数据的写入和读取的.解决大量用户并发访问的方案有很多,给你个千万pv的参考方案:1)架构中直接引入软件名称的模块,是个人推荐使用的,如Hapr ...

  3. Jersey服务端

    问世间情为何物,直叫人一声呵呵. 上个项目写的jersey restful服务端,怎么都是正确的,没什么问题.结果这个项目写了,呵呵了,真的呵呵了,怎么搞都有问题. 总是报错,对json的类型报错,无 ...

  4. LinqToHubble介绍及简单使用步骤——LinqToHubble是对HubbleDotnet的封装

    或许你还你知道HubbleDotnet,下面简单对HubbleDotnet坐下介绍. HubbleDotNet是由盘古分词作者——eaglet 开发的一个基于.net framework 的开源免费的 ...

  5. DevOps Workshop 研发运维一体化(北京第二场) 2016.04.27

    北京不亏为首都,人才济济,对微软DevOps解决方案感兴趣的人太多.我们与微软公司临时决定再家一场培训. 我之前在博客中(DevOps Workshop 研发运维一体化第一场(微软亚太研发集团总部)h ...

  6. 排序算法之堆排序(Heapsort)解析

    一.堆排序的优缺点(pros and cons) (还是简单的说说这个,毕竟没有必要浪费时间去理解一个糟糕的的算法) 优点: 堆排序的效率与快排.归并相同,都达到了基于比较的排序算法效率的峰值(时间复 ...

  7. umeng推送, 生产环境deviceToken失效可能原因

    1 在系统升级之后会造成app的deviceToken重置(一定). 2 在app卸载之后可能会造成app的deviceToken重置. 3 deviceToken重置使用umeng推送时会因为dev ...

  8. Android 美学设计基础 <2>

    我们接着上期的项目进行分享. 1.2.2 Elevation (仰角) 仰角只的是不同的素材块在Z轴上的选对位置 仰角的测量方式 这里只的是两个平面在z的距离,记住我们默认每个平面都是1dp的厚度 1 ...

  9. Memcached 查看列出所有key方法

    Memcached没有一个比较简单的方法可以直接象Redis那样keys *列出所有的Session key,并根据key get对应的session内容,但是还是可以查看的 memcached 查看 ...

  10. 使用python+selenium对web进行自动化测试

    想用python代码,对web网页进行自动化测试 web自动化测试和手动测试的区别: 手动测试:通过手动去对网页的功能进行点点点 web自动化:可以通过代码,自动对网页点点点 首先,将python+s ...