mybatis-plus 连接oracle数据库查询无任何报错 Row: 0

写在前面

这个坑我爬了很久,写的废话比较多,但是也不枉是一个比较好的解决问题的思路。若你非常着急,可以直接看总结,希望能帮到你。

背景

  项目中原先使用了mysql数据库,后来需要改为使用Oracle。使用了Navicat的数据同步功能,将表结构与数据傻瓜式同步过去了。

导入oracle的依赖,启动项目一切正常。但在执行具体的业务操作的时候发现找不到数据,控制台无任何报错,检查同步过来的数据库中的表又确实有数据。

百思不得其解,开启了Mybatis-plus的debug日志。观察日志发现,这个并没有执行到具体的语句,而是被mybatis-plus的分页拦截器拦截了。

问题分析

mybatis-plus的分页拦截器原理并不复杂,只是在你执行对应的select语句的时候,根据你连接的数据库自动在对应位置插入分页语句。比如mysql就是limit…offset…,oracle就是rownum<…

但是它能做的并不只有这个,它可以进行分页查询语句的优化。比如说你的查询语句是很长的left join语句,它会先统计一下总数(select count(1)),如果row等于0,就说明你的表中并没有记录,则将后续真正执行的查询语句给拦截掉了,不放行。我在项目中也配置了这个查询优化。

我花费大量的精力在拦截器上,我认为就是拦截器执行的语句有问题,我查阅了大量的资料,关于Mybatis-plus的拦截配置,百度上有人说是mybatis-plus的版本问题,有人说是oracle数据库的驱动问题……

花费大量时间无果,我将控制台打印的查询总数的语句复制到Navicat中执行,统计的总数也是0。

我感到绝望,认为是mybatis-plus的分页查询不好使,准备移除分页拦截器,引入pagehelper。这时候我突然想到,那移除了分页拦截器,先看看具体的语句能不能执行先。移除后执行,很失望,还是不行。控制台确实打印出具体要执行的语句了,拦截器的统计总数语句消失,日志上打印的row还是等于0。

这就说明了,不是分页拦截器的问题。是这个语句本身就有问题。那我代码什么都没改,就换了个数据库,也没报数据库语句执行异常,比如ora-xxx系列的错误,怎么就找不到结果呢?

我复制控制台的语句到Navicat中格式化后细细观察,认定这个语句就是没问题的,尝试着点击执行语句。天!搞了半天它执行成功了?语句是没问题啊!

那会不会是Oracle刚才坏掉了,现在才生效的?我试着在程序中执行,还是不行,row还是0。

新的疑难出现了,为什么navicat中可以正常运行的语句,到了程序的Mybatis-plus中又无法执行呢?

顺着这个问题,我又百度了一波 “navicat 能执行的语句到了mybatis-plus无法执行”,百度还是告诉我让我换版本,查看Mybatis是否引入之类的,答非所问。

我感觉这个问题已经超出我的能力范围了,主要是我在navicat上怎么测怎么灵,怎么好好的一个语句在不同地方还能不一样呢。

卡住在这里很久,起初我也被百度带偏了,一直认为是mybatis-plus的问题。我突然逆向思维一下,为什么不能是navicat特殊呢?有没有一个可能,是navicat帮我做了什么?

顺着这个思路,我在研究怎么能测出来navicat的特殊性。我想到了一开始的那个查询总数的语句,毕竟在这个语句下,navicat与mybatis-plus是一样的结果。

由于涉密原因,我简单描述一下那个语句的模样

select count(*) from (
	select * from tableName
		where tableName.a = xxx
			and tableName.b = xxx
			and tableName.c = xxx
)

我想到可能会是筛选的问题,将里面where的条件一个个移除,再执行语句。终于!在我移除了status的时候,总数返回不是0了!!!

问题解决

定位到是这个status字段的问题,那么这个字段到底做了什么?这个是一个状态的字段,存的值都是0或1。看了一眼表,里面那么多status为1的值,为什么却统计总数为0?莫非是真有可能1 != 1???
我点击一下Navicat中的status中的值,看了又看,很是疑惑,就是1啊,怎么会查不了呢。

看了很久……我猛然发现,这光标的位置不对!我按了一下左箭头,1后面还有个空格!所以真相就是 "1 " != "1"

解决这个问题很简单,将status用trim包起来就可以了trim(status)

程序可以正常跑了,但是我们前面的疑问还没有解决:这空格哪来的?为什么navicat运行可以正常运行?

我翻回去mysql中的表看,这个status没有中的1后面并没有空格,那就是数据同步的时候,跨数据库系统同步存在的方言差异问题。原本在mysql中status是属于char类型的,申请了空间为2,当你存入了一个1,它占空间是2,但是实际只有一个字符;mysql char类型到了oracle中成了nchar,同步的时候同样申请了2空间,当你存入的值是1,只有一个字符,oracle会自动给你补上一个空格。这就是空格的由来。

Navicat可能存在对第一层select作自动去除空格的功能,执行的时候将空格移除了,若被包住在里层则无法去除。

总结

检查select语句后的条件筛选,查看是否存在意料之外的空格。尽量使用Nvarchar2这种自动长度的数据类型。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值