mybatis(ibatis)中的动态sql<dynamic prepend="where"><isNotEmpty>的讲解

来源:互联网 发布:淘宝中国质造入口 编辑:程序博客网 时间:2024/05/21 13:55


ibatis的文档中,关于动态SQL的举例如下: 
Java代码  收藏代码
  1. <statement id="someName" parameterClass="Account" resultMap="account-result" >  
  2.   select * from ACCOUNT  
  3.   <dynamic prepend="where">  
  4.     <isGreaterThan prepend="and" property="id" compareValue="0">  
  5.       ACC_ID = #id#  
  6.     </isGreaterThan>  
  7.     <isNotNull prepend="and" property="lastName">  
  8.       ACC_LAST_NAME = #lastName#  
  9.     </isNotNull>  
  10.     <isNotEmpty></ isNotEmpty>
  11.   </dynamic>  
  12. order by ACC_LAST_NAME  
  13. </statement>  


当需要使用根据传入参数的值来动态组装SQL时,可以使用dynamic标签。 
dynamic元素可以包含多个条件比较元素,并且按照条件比较元素的表述对参数值进行比较,来组装动态SQL。 
这里主要的条件比较元素包含isGreaterThan、isNotNull、isEmpty…… 

dynamic元素和条件比较元素,都是组成动态SQL的一部分,其中的prepend属性根据实际情况的需要辅助的组装动态SQL。 

以上面的statement为例: 
1)dynamic的prepend只要检测到第一个为“真”的条件比较元素,则覆盖其prepend属性并组装where关键字为动态SQL的一部分。 
2)isNotNull的prepend只要检测到参数值满足比较条件,则前置组装and关键字为动态SQL的一部分。 

注意一点:上面的例子中,ibtis文档中说 - dynamic元素中的prepend属性“where”将覆盖第一个为“真”的条件比较元素(即isGreaterThan)的prepend属性 
按照这个理解,则第一个为“真”的条件比较元素(即isGreaterThan)的prepend属性是不需要的,或者“and”是不需要的,(ibatis文档中的原文是 For example, in the case of the first true condition, there is no need for the AND, and in fact it would break the statement) 则修改上述例子为 
Java代码  收藏代码
  1. <statement id="someName" parameterClass="Account" resultMap="account-result" >  
  2.   select * from ACCOUNT  
  3.   <dynamic prepend="where">  
  4.     <isGreaterThan property="id" compareValue="0">  
  5.       ACC_ID = #id#  
  6.     </isGreaterThan>  
  7.     <isNotNull prepend="and" property="lastName">  
  8.       ACC_LAST_NAME = #lastName#  
  9.     </isNotNull>  
  10.   </dynamic>  
  11. order by ACC_LAST_NAME  
  12. </statement>  

事实上,这样修改的结果导致最终SQL 变为 
“select * from ACCOUNT where ACC_ID = #id#    ACC_LAST_NAME = #lastName#” 
明显是有问题的。 

跟踪源码发现,ibatis在检测sqlTag的时候,调用了如下方法 
Java代码  收藏代码
  1. public void pushRemoveFirstPrependMarker(SqlTag tag) {  
  2.      
  3.    if(tag.getHandler() instanceof DynamicTagHandler) {  
  4.      // this was added to retain default behavior  
  5.      if(tag.isPrependAvailable()) {  
  6.        removeFirstPrependStack.addFirst(  
  7.            new RemoveFirstPrependMarker(tag,true));  
  8.      } else {  
  9.        removeFirstPrependStack.addFirst(  
  10.            new RemoveFirstPrependMarker(tag,false));  
  11.      }  
  12.     ……  

dynamic要覆盖第一个为“真”的条件比较元素的prepend属性,首先需要检测该tag的prepend是否可用(tag.isPrependAvailable()),如果不可用的话,即便该比较条件为“真”,则不会覆盖,只是单独的添加该比较条件元素下的SQL 

Java代码  收藏代码
  1. public boolean isPrependAvailable() {  
  2.   return prependAttr != null && prependAttr.length() > 0;  
  3. }  

由此可以看出,prepend可用的前提是prepend属性值已经设置,并且长度>0。 

这样的话就不难理解上述修改后的statement,为何SQL变更为“select * from ACCOUNT where ACC_ID = #id#    ACC_LAST_NAME = #lastName#”?因为ACC_LAST_NAME = #lastName#的前置prepend,被作为第一个为真的比较条件给删除了。 
正确的写法应该是 
Java代码  收藏代码
  1. <isGreaterThan prepend="and" property="id" compareValue="0">  

或者 
Java代码  收藏代码
  1. <isGreaterThan prepend=" " property="id" compareValue="0">  
1 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 183页中文 yellow中文字幕最新域名 超超人人中文字免幕费中文字幕 绝对中学生超卡哇视频 一频道中文字幕无线观看 一道中文不卡视频 中国中文字幕无线观看局域网 学妹开庖处疼流泪小说下载 学妹开庖处疼流泪视频网站 学生的母亲字幕中文翻译视频 中文不卡视频在线播放复古 学妹开庖处疼流泪视频 视频g 学妹开庖处疼流泪t 学妹开庖处疼流泪图新闻 学妹开庖处疼流泪漫画小说 学妹开庖处疼流泪高清 学妹开庖处疼流泪网站 039 年轻的老师3中文字中幕中国人 学妹开庖处疼流泪t小说 学妹开庖处疼流泪视频 视频中国 学妹开庖处疼流泪音频 中文字字视频人人 学妹开庖处疼流泪小说txt 学妹开庖处疼流泪视频 手机 视频字幕中文翻译 五姑娘中文视频版 小护土叫得太完整视频中文 上了瘾中文版视频 按摩院里的中国姑娘电影 五姑娘视频网搜 架起乳白腿一深一浅 9老师啪国线自产 老师你的水又多又甜视频 91国偷自产短视频网站 在卫生间里就做的视频 家庭毋HH伦s线播放中文字版 视频精二区 中文字 美国式 柰忌轧伦中文 二十三又嫩水又多 家庭毋HH伦s中文字幕 毋HH伦中文字幕视频