Mybatis-那些让人摸不着头脑的报错

本想着,上篇关于Mybatis的文章《MyBatis-从查询昨天的数据说起》只是介绍RabbitMQ以及Spring AMQP中间的一剂调味剂。说说Mybatis是如何完成从sql到对象之间的映射并实现我统计数据的业务逻辑。

但因为上一个流水统计的任务开展比较顺利,所以后面索性又做了个前台展示(后面会再开一篇说说前端以及Bootstrap的一个控件的用法)。显然有展示,必然要有数据,于是又和Mybatis大了两天的交道,对它又有了一些深刻的认识。这里做一个简单的总结,希望不要踩我踩过的坑。

越忙越错的低级bug

上篇已经介绍过Mybatis存在的弊病和过于形式化,这次还要补充一点,那就是有些极其明显的错误需要等到运行的时候才能被发现。

有时候,我们难免会遇到项目很赶的时候,一个功能急等上线,但是仔细看了一眼项目的代码,发现都有现成的代码可以套用,心中暗自窃喜。
于是开始拷贝Dao类,开始拷贝xml文件,再改改其中不一样的sql语句,已经要定义的ResultMap中的映射字段等等,一眼望去,完全没毛病。于是开始打包上测试,然后执行业务操作,发现没有达到预期的效果,再回头看了一眼log,想一掌拍死自己的心都有了。因为你可能仅仅是因为忘记在ResultMap添加需要的一个字段,又或是sql语句中在不该出现的地方出现了一个“,”。要知道,在编译器,Mybatis可是慈眉善目的大善人,等你一旦上车,你会发现他的眼里是容不下一粒沙子,即使是一个“,”也不行。

org.apache.ibatis.binding.BindingException: Invalid bound statement (not found)
如果你经常和Mybatis打交道,那么对于上面这个报错一定不陌生。你需要仔仔细细的从如下几个方面好好排查
检查xml文件所在的package名称是否和interface对应的package名称一一对应

检查xml文件的namespace是否和xml文件的package名称一一对应

检查函数名称能否对应上

笔者就吃过第二项的亏。上面的三条即使排查问题的方向,也是需要注意的点,因为不满足其中一点,Mybatis都没法让你如愿执行sql语句,然而这一切在执行之前看的都再正常不过了。

ResultMap的一个小常识

上篇我们有提到返回结果定义的ResultMap,同是还提到了定义输入参数的PrameterType。假设现在有这样的一个ResultMap,其中就映射了一个字段identityCardId

image.png

这时候我们在Mybatis的配置文件中写出我们想要查询的sql语句,完全没有问题,可以得到你想要的结果。

Mybatis-那些让人摸不着头脑的报错_第1张图片
image.png

但是如果我们将查询的sql语句“select identity_car_id”改为“select identity_card_id as id”,那么此时ResultMap中的column就要改为id,即使数据库中并不存在id这个字段,因为你在查询的过程中已经将其重命名为id了。

Mysql的小常识

笔者将一个删除符合条件数据的sql语句写到mybatis中,在执行的时候发现报错

MySQL can’t specify target table for update in FROM clause
后来仔细一查才知道,这是Mysql在更新数据报错删除数据时对于from后面是sql子句就会出现问题。
比如执行这样的语句就会报错
“delete from t_official_sys_user
where USER_NAME IN(SELECT USER_NAME FROM t_official_sys_user b group by b.USER_NAME having count(1) > 1)”
需要改为

delete from t_official_sys_user
where USER_NAME IN(select USER_NAME from ( SELECT USER_NAME FROM t_official_sys_user b group by b.USER_NAME having count(1) > 1) as temtable ); ”

也就是说需要将要删除的表先存为一张中间表,然后才能删除。
另外还需要注意一点的是,对于存为中间表的表需要对其命名,就像这里的“as temtable”,否则会报错“Every derived table must have its own alias”。

你可能感兴趣的:(Mybatis-那些让人摸不着头脑的报错)