【mybatis】mybatis plus insert update失败 记录一次特殊而诡异的事件

mybatis plus封装了 updateById ,update(entity,wraaper),update(wraaper)等方法,最近在开发中,遇到了无论用哪个,都update失败了,怪就怪在A表是update成功的,但是B表update失败。

排查思路:

  1. 反反复复仔细检查,B相关xml的映射路径 和entity的注解、字段,都是没有问题的,不会因为这种低级错误半天还发现不了。
  2. 查询数据库是否有死锁 然而发现一切正常
  3. 接着检查了class文件,也确实有编译,在这两天开发中,B数据库表有过字段名的一次变更,实体类也有跟着变更,class文件里面也是变更后的内容;
  4. 最后想到,会不会是序列化的问题,A和B两个实体类 都是serialVersionUID=1L; 可是之前模块代码都是这么写的,mybatis plus代码构造器 默认生成就是这样,于是抱着试试看的尝试,将两个UID改成不一致的,重启服务后,意外发现update竟然成功了,再接着将两个都改回成1L 也是不再报错了。

bug重现

上次改serialVersionUID 意外成功后,心里一直很疑惑,不同的两个类 serialVersionUID = 1L 的确不应该有问题才对,如果这是bug导致的最终原因 那很难说服自己,后面更新了一下svn,由于自己开发时 不小心将实体类的class文件上传上去了,update下来后,发现问题复现,A表update成功 B表失败,把class文件删除后,确保重新编译过,pom重新导入,发现还是报错。

再次排查:
  1. 先确定是不是只有update有问题 于是分别调用了select和insert,发现B表的select成功,insert失败,(中途试过注解形式和xml形式 但其实这是无用功 结果都是一样 update失败),那么问题就初步确定了:
    (1). executeupdate()有问题 executequery()正常
    (2). 连接数据库是正常的 因为select没问题
    (3). 换传统jdbc尝试 executeupdate()也是正常的,再次验证jdbc conn是正常的
bug升级

再后来,为了方便测试,把A,B的mapper层 注入到testController里面 ,发现A,B表都update 、insert失败
补充一点,全程都是try catch 不到信息的,异常在框架底层被捕获了,已知动态代理出现异常 ,其中一处报错是
PROPAGATION_REQUIRED,ISOLATION_DEFAULT; ‘’,-java.lang.Exception ,网上无法就是说注解错误、开启事务之类的,我们直接写在controller里面 没有开启事务,所以没有任何参考价值。但是mapper.select()是正常的,说明mapper映射应该没问题。再后面 一步步跟源码报的异常,发现其中一处:org.springframework.web.util.NestedServletException: Handler dispatch failed; nested exception is java.lang.NoClassDefFoundError: org/springframework/security/core/context/SecurityContextHolder

这里再补充一下,项目为maven聚合项目,我们其中封装了一个基础模块,用于被其它模块引入,而基础模块中,有用到security 有相关配置类 有利用spi机制启动的配置,然而在我自己的项目模块中,使用的是shiro,于是把oauth2依赖给排除了,所以报这个错误也是很自然的,而且看到catch后面还有finally 也没有在意, 因为自己的模块没有用到oauth2权限认证,它也不应该会影响mybatis的操作。

最后再整理思绪,突然想到是在动态代理的时候报错,而security相关的类 有把bean交给spring托管,依赖被我排除了,动态代理报错是很正常的,那这个代理失败,会不会影响mybatis (plus)的动态代理执行呢? 于是把security相关代码都给注释,发现mybatis plus的insert update果然成功了!

总结

由于存在前置动态代理出错,导致mybatis plus动态代理没执行 所以update insert失败,

但仍有很多疑惑:
  1. 为什么一开始是一张表可以 一张表不行呢? 期间配置文件没有更改
  2. 为什么springboot启动时 缺少oauth2依赖却没有报错呢?
  3. class文件从svn更新下来 代码不变的前提下,已经把更新下来的class文件删除 重新编译过了,和svn更新前 有什么区别呢? 而之前更改序列化版本号意外成功 本质很可能是class的一次重新编译 但是后来改回1L 了 改回后也确认再次有所编译 ,这两个现象似乎说明class中还存在些奥秘
  4. spring作为一个粘合剂,为什么其它框架的动态代理出错 会导致mybatis plus的动态代理执行失败呢?是spring设计问题 还是mybatis plus设计存在问题呢

Guess you like

Origin blog.csdn.net/qq_36268103/article/details/115725679