记录一个使用ibatis开发的碰到的问题

问题记录:

使用ibatis开发的时候使用dynamic标签做动态sql拼接的时候

<dynamic prepend="where">
t.ATTRIBUTE10 in ('attribute10')
<isNotEmpty prepend="AND" property="attribute1">
    t.ATTRIBUTE1 = #attribute1#
</isNotEmpty>
</dynamic>

拼接出来的sql 为 where t.ATTRIBUTE10 in ('attribute10')  t.ATTRIBUTE1 = #attribute1# 当中缺了and关键字,导致查询sql的时候报

java.sql.SQLException: sql injection violation, syntax error: TODO :

的错误。

解决问题:

为什么没有加上and关键词?

猜测一:

在sqlsessionTemplate初始化的时候就没标记上

在容器初始化MappedStatementConfig打上断点开始排查

发现dynamic标签的都有成功的标记为sqlText和sqlTag类型,并没有漏掉and关键字

都有标记成功,说明在初始化的时候并没有漏掉and关键字

从中还可以得出一个结论,在容器初始化的时候,ibatis就会开始解析xml里的sql,并封装成一个个children类型的对象数据,将里面的标签标记为sqlText对象或者sqlTag对象

猜测二:

在拼接的时候由于某些判断没拼接上

重新断点,将断点打在查询的逻辑上

最终将方法定位在DynamicSql对象中 processBodyChildren()方法中的 doPrepend() 方法上,在这个方法上

断点打入,首先sql容器会从谷歌初始化完的children拿到所有这个查询下的数据,然后开始做解析,首先解析第一个sqlText类型,普通的select * from xxx查询的String append到out对象上,然后解析第二个SqlTag类型,这个就是dynamic标签中的所有都存储在这个对象中,打开来看

children里存着sqlText,sqlTag,sqlText类型,分别对应着 

t.ATTRIBUTE10 in ('attribute10')
<isNotEmpty prepend="AND" property="attribute1">
    t.ATTRIBUTE1 = #attribute1#
</isNotEmpty>

和一串空字符

继续往下执行,解析到isnotEmpty这个标签的sqlTag的时候,继续递归进去,里面也是sqlText

将这个sqlText拿出来,返回之后

body里面就是 isnotEmpty 标签里的 t.ATTRIBUTE1 = #attribute1#,tag里就是前序的t.ATTRIBUTE10 in ('attribute10') 这个String,然后就会进到doPrepend() 这个方法中去拼接 and

走到这步发现,他并没有拼接 insert and 而是去执行了 disableRemoveFirstPrependMarker()将第一次栈中的设置为了false。也就是说,

ibatis并没有对前序的sqlText = t.ATTRIBUTE10 in ('attribute10') 做判断,而是默认这个t.ATTRIBUTE1 = #attribute1# 为第一个,所以不需要 + and 关键字,所以就没有拼接上and,但后续isnotempty由于不是第一个,自然就会走到else的逻辑判断中,拼接上and关键字。

所以修改写法,将 isnotempty 标签的动态sql放到第一个,这样sql就能正常拼写成功,并查询成功了。

注:ibatis使用版本:2.3.4

  • 44
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值