问题来源
异常:
org.apache.ibatis.reflection.ReflectionException: There is no getter for property named 'phoneType' in 'class java.lang.Integer'
问题描述:一个单参的DAO层接口,映射到mybatis的xml语句,其中使用了
if test
字句,使用name方式读值,发生如上异常。其具体接口与实现如下:
public AppVersion findNewestVersion(int phoneType);
<select id="findNewestVersion" parameterType="int" resultType="com.model.bean.entity.AppVersion">
SELECT id, name, version, description, apkPath, iosState, createTime, lastUpdateTime, createUserId
FROM commentsys_app_version
<where>
<if test="phoneType == 2">
iosState = 1
</if>
</where>
ORDER BY createTime DESC
LIMIT 1
</select>
原因分析
回想起之前写Mybatis的接口,多个参数的时候习惯性是写
@Param
注解或者放到map中,然后在xml中用#{name}
取值即可。而单个参数通常是没写注解,直接利用#{name}
取值的。这样做似乎没有什么问题、
问题出在哪里呢?
if test
字句!
我们知道,
mybatis
默认是按照顺序进行传参的,所以多参情况下,可以用#{param1}
、#{param2}
…这样的形式读取。
这个时候,如果我们在SQL语句中使用#{name}
来取值,不会有任何问题,因为Mybatis
找不到这个name的值,所以会默认找到第一个参数,即param1
。
但是,我这里还使用了<if test="phoneType == 2">
,这个时候就出现问题了,mybatis
试图从Integer
这个对象中读取name为phoneType
的属性,然而这个值不存在,于是报错(嘿嘿这个过程纯属个人猜测,非官方解说)
解决办法
从上面的个人分析来看呢,比较好的解决思路就是给参数加上
@Param
注解:
public AppVersion findNewestVersion(@Param("phoneType")int phoneType);
至于
XML
中的代码则不需要进行修改。
总结思考
从上面的问题可以发现,在
Mybatis
中,使用@Param
对参数进行注解是一个很好的实例,而另一方面呢,如果是多个参数,不妨将参数封装在Map
中进行传值,这样不仅可以避免多参数无法取值的问题,还能实现动态的SQL。比如:// 使用注解 public User find(@Param("name")String name, @Param("password")String password); // 使用Map public User find(Map<String, Object> map); // map中有两个key,一个是name,一个是password