ibatis动态查询
在复杂查询过程中,我们常常需要根据用户的选择决定查询条件,这里发生变化的
并不只是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动态查询的更多相关文章
- ibatis动态查询条件
ibatis的调试相对困难,出错的时候主要依据是log4生成的log文件和出错提示,这方面要能比较熟练的看懂. 下面这个配置基本上包含了最复杂的功能:分页\搜索\排序\缓存\传值Hash表\返回has ...
- ibatis 动态查询
http://www.iteye.com/topic/393042最近做了很多动态的查询,尤其是排序,以及一些状态字段,所以就做了一个总的动态查询,以不变应万变,呵呵 ibatis 里面的sql代码: ...
- ibatis动态多条件查询及模糊查询(oracle,mysql,sql)
首先是模糊查询的问题,开始时我使用如下条件:select * from user where name like '%#value#%'. 可是怎么也不行,好像还报错了.后来在网上找到了解决方法,就是 ...
- Ibatis动态(dynamic)查询
Ibatis的动态查询使得数据操作变得非常的灵活,下次举出了常用的动态查询的属性信息: Ibatis配置信息 <!-- Dynamic Sql --> <typeAlias a ...
- ibatis Dynamic总结(ibatis使用安全的拼接语句,动态查询)
ibatis中使用安全的拼接语句,动态查询,ibatis比JDBC的优势之一,安全高效 说明文字在注释中 一.引入 一个小例子 <select id="selectAllProduc ...
- ibatis 取消查询动态列的缓存
ibatis在查询结果列不确定(或是动态变化)的情况下,会因为列缓存的原因导致变化后的列数据查不出来 解决方法是: select标签有个属性remapResults,该属性默认值为false,设置成r ...
- 转:ibatis动态sql
转:ibatis动态sql 直接使用JDBC一个非常普遍的问题就是动态SQL.使用参数值.参数本身和数据列都是动态SQL,通常是非常困难的.典型的解决办法就是用上一堆的 IF-ELSE条件语句和一连串 ...
- Ibatis动态拼装sql,常用标签总结及举栗子。
今天得到项目经理一项任务,就是拼装sql,第一次见到,不是太懂,赶紧回来睡一觉再说,由于这次的项目orm使用的是ibatis框架,所以需要使用动态拼装sql,或者是ognl语言,这门语言不是专属于ib ...
- IBATIS动态SQL(1)
转:IBATIS动态SQL 直接使用JDBC一个非常普遍的问题就是动态SQL.使用参数值.参数本身和数据列都是动态SQL,通常是非常困难的.典型的解决办法就是用上一堆的IF-ELSE条件语句和一连串的 ...
随机推荐
- [大牛翻译系列]Hadoop(18)MapReduce 文件处理:基于压缩的高效存储(一)
5.2 基于压缩的高效存储 (仅包括技术25,和技术26) 数据压缩可以减小数据的大小,节约空间,提高数据传输的效率.在处理文件中,压缩很重要.在处理Hadoop的文件时,更是如此.为了让Hadoop ...
- glibc学习介绍篇
C语言自身并没有提供IO,内存管理,字符串操作等类似的机制.作为弥补,C语言有一个标准库帮助C语言实现这些机制.我们在编译C程序的时候基本上都需要链接到这些库文件. GNU C Library定义IS ...
- 如何参与linux 内核开发
如果想评论或更新本文的内容,请直接联系原文档的维护者.如果你使用英文 交流有困难的话,也可以向中文版维护者求助.如果本翻译更新不及时或者翻 译存在问题,请联系中文版维护者. 英文版维护者: Gre ...
- java的JVM机制
1.jre:java运行环境 提供一个JVM和一些基础类库.2.只安装jre以后,机器就具备了运行java程序的条件.但是不具备开发java程序的条件.安装JDK以后,在c:/program file ...
- PHP中日期时间函数date()用法总结
date()是我们常用的一个日期时间函数,下面我来总结一下关于date()函数的各种形式的用法,有需要学习的朋友可参考. 格式化日期date() 函数的第一个参数规定了如何格式化日期/时间.它使用字母 ...
- DB天气app冲刺二阶段第五天
昨天什么事情也没做..看了一场哆啦a梦 所以就不算冲刺了.. 今天主要就是做了一下需要用到的图片的整理还有的就是UI主界面需要展示用的素材,发现好多东西都需要搜索半天,虽然这个不是什么技术活..但真的 ...
- Ext学习-布局介绍
1.目标 了解ExtJS中的关于布局和组建的相关原理,并学习相关的布局方式 2.内容 1.布局和组件的相关原理 2.常见的布局方式 3.学习流程 1.首先应该学习一下布局和组件的相 ...
- MVC3+AutoFac实现程序集级别的依赖注入
1.介绍 所谓程序集级别的依赖注入是指接口和实现的依赖不使用配置文件或硬代码实现(builder.RegisterType<UserInfoService>().As<IU ...
- C#根据日期DateTime和持续时间int找到日期
protected DateTime GetFinish(DateTime start, int duration) { return start.AddDays(duration); } prote ...
- 【WCF--初入江湖】07 分布式事务
07 分布式事务 一.前言 [1]理解事务特性 [2]掌握TransactionFlow 特性 [3]掌握WCF中的事务属性 TransactionAutoCompleteOnSessionClose ...