ibatis的dynamicSQL中,关于prepend的使用

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.   </dynamic>  
  11. order by ACC_LAST_NAME  
  12. </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">  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值