Ibatis缓存select字段名引起的问题

开发中遇到一个问题,网上有人描述问题,但是没有找到答案,自己看了ibatis源码才明白过来
执行SQL:
<select id="searchOrderListConut" resultClass="int"> SELECT count(<isEqual property="useTicketTb" compareValue="true"> distinct </isEqual> o.id) FROM et_orders o <isEqual property="useTicketTb" compareValue="true" prepend=","> tickets ticket </isEqual> .................这里省略 </ select>
抛出如下异常:
com.taobao.et.biz.dal.exception.DAOException: org.springframework.jdbc.BadSqlGrammarException: SqlMapClient operation; bad SQL grammar []; nested exception is com.ibatis.common.jdbc.exception.NestedSQLException: --- The error occurred in com/taobao/et/biz/dal/ticket/dataobject/order_sqlmap_mapping.xml. --- The error occurred while applying a result map. --- Check the orders.searchOrderListConut-AutoResultMap. --- Check the result mapping for the 'COUNT(O.ID)' property. --- Cause: java.sql.SQLException: 列名无效
 
 
先描述一下场景:
 订单和机票表是一对多的关系,这条语句是根据机票表中的一些条件和订单中的条件进行分页查询的语句,这里是统计总数。
 由于机票表很少查询,所以DBA要求没有查询机票表的时候就不要关联机票表,并不需要distinct关键字。于是就出现了下面这条动态SQL语句,先不管这条语句是否变态,我说说明的问题是,这条语句在上线运行是会出问题的(单元测试不会有任何问题),为什么呢?答案源自于sqlmap的自身的一个处理方式。
 
     sqlmap在执行这条SQL的时候会根据orders.searchOrderListConut这个key来查找select返回的列表字段,如果没有找到,就会分析这条SQL,然后使用orders.searchOrderListConut做为key,selelect中返回的字段列表作为value缓存起来备用(问题就是在这里),以后每次查询这条searchOrderListConut语句的时候,就会直接从缓存中拿出返回字段。假设这条语句先执行了select count(o.id) from et_orders o.....,那么这里缓存起来的字段就是count(o.id),而第二次查询时假设查询了机票表中的信息,那么就需要时select count(distinct o.id) from et_orders o..... ,这时,ibatis使用缓存起来的count(o.id) 作为字段名来取,当然就会取不到值,从而抛出一个异常。
 
 
ibaits中缓存列名的地方在这里:
 
com.ibatis.sqlmap.engine.mapping.result .AutoResultMap public synchronized Object[] getResults(StatementScope statementScope, ResultSet rs) throws SQLException { if (allowRemapping || getResultMappings() == null) { initialize(rs); } return super.getResults(statementScope, rs); }
 
 
知道了这个原因,那么问题就可以解决了。既然是根据select 的id缓存了字段名,那么就可以从这里下手了,先不管方法优劣,解决办法如下:
1:既然缓存了,那么第一个方法就是去掉这个缓存。(这个能解决问题,但是不好,又麻烦,又影响性能),之所以单元测试没有发现这个问题,就是因为,单元测试是跑一次就停下来了,再跑第二次,所以这个缓存相当于没有。
2:给这个动态变化的字段增加一个别名,例如
SELECT   count(<isEqual property="useTicketTb" compareValue="true">  distinct  </isEqual> o.id)  num
这样缓存中就会留下num别名作为字段名,至于前面如何变化,ibatis不管
3:自然就是SQL语句拆分,将要关联机票表和不关联机票的SQL语句分开,就不会存在这个问题了。

转载于:https://www.cnblogs.com/lovingprince/archive/2009/07/02/2166310.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值