There is no getter for property named '*' in 'class java.lang.String
来源:互联网 发布:出售淘宝旗舰店id 编辑:程序博客网 时间:2024/06/05 11:08
一、错误再现
想要追本溯源,就需要错误再现,那么假设我们有这样一个sql查询:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
parameterType="String"
,这一点是必须得,参数类型必须是string。- 该sql对应的mapper class中对应的方法为
List<Member> getRiskMember(String username);
,也就是说,传递的参数名为username,正常情况下,这样的配置合情合理。 <when test="username != null">
,你有一个对应的test判断语句,也可能是if。- 那么这个时候,项目运行该查询语句时,就会抛出
There is no getter for property named 'username' in 'class java.lang.String'
错误!
二、解决办法
当然了,如果你没有时间来看源码分析实例的话,我想先告诉你解决办法,免得你被问题困扰。解决办法很简单,你只需要把<when test="username != null">
修改为 <when test="_parameter!= null">
就好了,其他地方不需要改动(也就是说and username = #{username}
不需要改动为and username = #{_parameter}
),修改后的sql语句如下:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
三、源码分析
当然了,如果你有时间的话,看一看源码分析,或者自己动手尝试一下,我相信你一定会大有所获!
①、准备源码包
你需要这样两个文件,具体怎么下载我就不多说了,如果你需要的话,也可以加群120926808:
- mybatis-3.2.3-sources.jar
- mybatis-spring-1.2.2-sources.jar
当然了,你项目中对应的lib包也是相应的版本。
然后,我们把对应的源码进行反编译,生成对应的source,使用的工具是jd-gui.exe。
紧接着,我们来看看如何关联源码包,见下图:
我已经加载好了,如果是首次的话,可点击edit,在弹出的提示框中选择上一步保存的zip文件。
②、测试用例
准备好源码包后,我们来写一个测试用例,直接main方法就可以,当然了项目不同,方法自然不同,简单的如下所示:
- 1
- 2
- 3
- 4
- 5
- 1
- 2
- 3
- 4
- 5
我们在mapper.getRiskMember("00010001");
这行打上断点。
③、debug调试
直接运行main方法,在断点处F5,进入到MapperProxy.java
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 1
- 2
- 3
- 4
- 5
- 6
- 7
可以尾随debug进入到MapperMethod.java
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
进入到该方法后,可以一直调试到result = sqlSession.<E>selectList(command.getName(), param);
该行代码。此时,你需要按住ctrl键,同时点击鼠标左键,见下图:
在弹出框中选择open implementation,然后进入到DefaultSqlSession.java
- 1
- 2
- 3
- 1
- 2
- 3
在return this.selectList
行上打上断点,然后按F8快捷键进入到该方法继续调试,(限于篇幅,省略步骤,后续文章中使用…代替)、直到你进入到CachingExecutor.java
- 1
- 2
- 3
- 4
- 5
- 1
- 2
- 3
- 4
- 5
tips:猫腻就在BoundSql boundSql = ms.getBoundSql(parameterObject);
这行代码的执行过程中。
(…)(省略步骤,个人调试过程中请注意。)
直到你进入到DynamicContext.java类时
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
此时,你不妨wait a moment,翻看一下该类的整体代码,你会发现:
- 1
- 2
- 1
- 2
这里有两个常量,当然了,但看此处,也许你会发现"_parameter"
这个关键字,但这时还说明不了什么,你且记住bindings.put(PARAMETER_OBJECT_KEY, parameterObject);
,同时对ContextMap bindings
对象留有一点印象。
key1:_parameter
(…)(省略步骤,个人调试过程中请注意。)
然后,我们进入MixedSqlNode.java
- 1
- 2
- 3
- 4
- 5
- 6
- 1
- 2
- 3
- 4
- 5
- 6
该apply方法就非常有意思了,xml里配置的sql语句,会通过该方法转换为标准的sql(称之为标准,是值这形成的sql语句就是能够执行预处理sql查询的字符串),你不妨慢一点执行该循环语句。
第二次循环的时候,你就可以看到sql的雏形了,那么请继续。
(…)(省略步骤,个人调试过程中请注意。)
直到你发现,sqlNode的类型为ChooseSqlNode,此时,你是否已经能联想到以下内容:
- 1
- 2
- 1
- 2
事情开始变得明朗起来,真好。
(…)(省略步骤,个人调试过程中请注意。)
继续调试,直到你进入到ExpressionEvaluator.java
- 1
- 2
- 3
- 4
- 5
- 6
- 1
- 2
- 3
- 4
- 5
- 6
- expression的值为
username != null
- parameterObject的值为
{_parameter=00010001, _databaseId=null}
- 以上两个参数之间好像有点关系,但离源泉处还差那么几步,请继续。
紧接着,我们进入到OgnlCache.java
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 1
- 2
- 3
- 4
- 5
- 6
- 7
进入到OgnlCache.java
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
key2:
1. parseExpression(expression)
的类型为Node,其值为username != null
。
2. root的类型为DynamicContext$ContextMap (id=41)
,其值为{_parameter=00010001, _databaseId=null}
(…)(省略步骤,个人调试过程中请注意。)
当再继续执行的话,就回到了DefaultSqlSession.java
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
此时错误已经抛出了,见下图
到了这,异常是找到怎么抛出了,但整体看上来,好像又缺点什么,没错,由于eclipse中无法再看到Ognl.getValue(parseExpression(expression), root);
,所以就会造成困扰,我们通过反编译工具,可以看到getValue方法。
- 1
- 2
- 3
- 4
- 5
- 1
- 2
- 3
- 4
- 5
- 1
- 2
- 3
- 4
- 5
- 1
- 2
- 3
- 4
- 5
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
此时再结合key2给出的内容,我们可以知道,要在{_parameter=00010001, _databaseId=null}
匹配到porperty为username
的值是不可能的啦,这样的话,程序就会抛出org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.reflection.ReflectionException: There is no getter for property named 'username' in 'class java.lang.String'
错误了!
- There is no getter for property named '**' in 'class java.lang.String
- mybatis There is no getter for property named 'xx' in 'class java.lang.String
- Mybatis中传参包There is no getter for property named 'XXX' in 'class java.lang.String'
- Mybatis-There is no getter for property named 'XXX' in 'class java.lang.String'解决办法
- Mybatis中传参包There is no getter for property named 'XXX' in 'class java.lang.String'
- mybatis:There is no getter for property named 'xxx' in 'class java.lang.String'
- There is no getter for property named '**' in 'class java.lang.String'
- Mybatis-There is no getter for property named 'id' in 'class java.lang.String'
- mybatis There is no getter for property named 'xx' in 'class java.lang.String
- Mybatis中传参包There is no getter for property named 'XXX' in 'class java.lang.String'
- There is no getter for property named 'num' in 'class java.lang.String'。
- There is no getter for property named 'XXX' in 'class java.lang.String'
- There is no getter for property named 'itemId' in 'class java.lang.String 异常处理
- Mybatis中传参包There is no getter for property named 'XXX' in 'class java.lang.String'
- mybaits错误解决:There is no getter for property named 'id' in class 'java.lang.String'
- MyBatis There is no getter for property named 'xxx' in 'class java.lang.String'
- mybatis There is no getter for property named 'xx' in 'class java.lang.String
- Mybatis中传参包There is no getter for property named 'XXX' in 'class java.lang.String'
- UVa 220 Othello
- easyui datagrid 导出excel及乱码解决
- 什么是线下售前精准营销系统--来就推功能详解
- Linux 1. 奇怪符号 ^@
- ODI 12c连接Oracle Hyperion Planning 11.1.2.4数据源
- There is no getter for property named '*' in 'class java.lang.String
- 第3章 寄存器(内存访问)
- 一个java程序员如何从新手慢慢成长
- AngularJS中实现奇偶行不同样式
- js仿照聊天记录的时间显示 今天 昨天
- VMWare虚拟机无法打开内核设备"\\.\Global\vmx86"的解决方法
- 清除position:relative占用的空白
- CG中的几何学——矩阵【4】
- Elasticsearch集群部署详解