There is no getter for property named ‘__frch_item_0‘ in ‘class

前言

There is no getter for property named ‘__frch_ _0’ in 'class,好不容易将ssm改造成了springboot,发现不少的sql报了这个错误。

解决

■ 搜索报错原因

以下为搜索出来的代表性解答——

在这里插入图片描述
。。。。。

■ 解析三种方式

① #{}

按照这个报错搜索都会说这个是错误写法。这个否决才是错的,我一开始还真信了,以为ibatis高版本真的不再支持这个写法了。所以问了不少同学,他们在高版本中仍然采用#{}这个写法,这就确定了报错跟版本无关,并且常规情况下#{}是正确写法。
效果——
paramName例子:__frch_item_0
frch是foreach的缩写;
item是foreach标签里item的值;
0是下标,即0,1,2,3遍历list.size。

所以很多人不明白自己没定义这个参数,却有这堆乱七八糟的字符。

② ‘${}’

占位符,直接拼接不走预编译,有sql注入风险,很多帖子让人直接改成’${}’,基础差的话还真信了,这是要被祭天的操作。
效果——
直接拼接进sql语句。

③ #{list[${index}]}

这倒是个神奇的写法,相当于遍历list[index]。
效果——
paramName例子:list[0]
list是list属性名
0是下标,即0,1,2,3遍历list.size。

■ 自查报错原因

现已得知,不论哪个版本#{}都没错。另辟蹊径改用第三种写法,一是非常规可读性差,二是代码实在多改动太多容易引发重大事故。便查看配置,最后发现去除分页拦截后不再报错,这才恍然大悟之前有的foreach正常,有的却报错,报错的是因为被分页拦截,也就说明版本升级后,分页插件的代码有误。

■ debug源码

① 查看抛错根源

org.apache.ibatis.reflection.Reflector
在这里插入图片描述
可得,确实是找不到属性名,往前查看是怎么获得value的。

② 查看报错的是怎么获得value

在这里插入图片描述
得知前几个方法都没进去,最后else,强行走了MetaObject的getValue()方法,参数为__frch_*_0自然报错,如果采用前文所说的#{list[${index}]}则是list[0],可获得value。然后我回到旧项目debug,发现foreach走的是hasAdditionalParameter为true,并且value等于getAdditionalParameter,而新版中hasAdditionalParameter为false。

③ 查看hasAdditionalParameter的不同

org.apache.ibatis.mapping.BoundSql

3.3.0
public boolean hasAdditionalParameter(String name) {
    
    
	return this.metaParameters.hasGetter(name);
}
3.3.1 ~ 3.4.1
public boolean hasAdditionalParameter(String name) {
    
    
	PropertyTokenizer prop = new PropertyTokenizer(name);
    String indexedName = prop.getIndexedName();
    return this.additionalParameters.containsKey(indexedName);
}
3.4.6 ~ 3.5.6
public boolean hasAdditionalParameter(String name) {
    
    
	String paramName = (new PropertyTokenizer(name)).getName();
        return this.additionalParameters.containsKey(paramName);
}

原因找到了,老版通过metaParameters判断参数,新版通过additionalParameters判断参数。
而getAdditionalParameter一直没变,都是通过metaParameters

public Object getAdditionalParameter(String name) {
    
    
	return this.metaParameters.getValue(name);
}

④ 解决

得知新版需要用到additionalParameters参数,也就是说不论哪个版本,value都是从metaParameters获得,在新版中使用了additionalParameters判断是否有值。而分页插件没有注入该参数,用ref加入该参数(注释的代码),问题解决。
在这里插入图片描述

⑤ 最后确认

查看常规走向——取消分页拦截,查看高版本Mybatis的foreach走法
org.apache.ibatis.scripting.defaults.DefaultParameterHandler
在这里插入图片描述
与分页插件重写的方法一致,都是hasAdditionalParameter为true后,通过getAdditionalParameter获取value。

最后

习惯性搜索报错把我坑惨了,更改第三种写法一半发现实在太多了,还容易改错,浪费了大半天时间,如果早点下拉到最下方的异常自然就会发现来自分页报错,也就能更快的解决问题。

Guess you like

Origin blog.csdn.net/qq_24054301/article/details/114469803