应用场景:
// DAO层接口
public List<ValidUrl> findValidList(Boolean enable); // 注意这里是Boolean类型,而不是基本数据类型boolean
<!-- xml sql语句>
<select resultMap="ValidUrlMap">
SELECT id, sourceId, url_pattern, isEnable as enable
FROM commentsys_url
<where>
<if test="enable != null">isEnable = #{enable}</if>
</where>
</select>
运行报错:ReflectionException: There is no getter for property named ‘enable’ in ‘class ’
解决办法:
1.使用@Param注解标识参数
public List<ValidUrl> findValidList(@Param("enable")Boolean enable)
注:这种方式只需要在接口中添加@Param注解即可。
2.使用_parameter表示if test=“”中代替enable
<!-- xml sql语句>
<select resultMap="ValidUrlMap">
SELECT id, sourceId, url_pattern, isEnable as enable
FROM commentsys_url
<where>
<if test="_parameter != null">isEnable = #{enable}</if>
</where>
</select>
注:这种方式需要修改if-test语句中使用的参数,用_parameter代替对应的name。
问题分析
乍一看原先的代码是没问题的,但如果联想到Mybatis参数映射的机制就会发现有些东西不一样了。我这里使用了boolean的包装器类型Boolean,这是个Object啊!而我们通常是如何获取对象里的某个值的呢?——get方法。但是Boolean类型并没有实现所谓的get方法,所以肯定会出问题。
这也是为什么以下的语句可以正常运行的原因:
public List<Events> find(User user); // 根据user找对应的事件
<select parameterType="" resultType="">
SELECT * FROM events WHERE userId = #{id}
</select>
原因就在于User对象里有get方法啊(不会有人写bean类不实现getter和setter吧?)
这里再阐述一下Mybatis SQL查询参数映射到查询语句时的机制。
相信大家都知道以下两段代码在效果上是一样的:
第一种方式:按name获取
public User find(@Param("name")String name, @Param("password")String password);
<select resultType="">
SELECT * FROM user WHERE name = #{name} AND password = #{password}
</select>
第二种方式:按index获取
public User find(String name, String password);
<select resultType="">
SELECT * FROM user WHERE name = #{0} AND password = #{1}
</select>
从第二种方式可以看出来了,Mybatis传值的时候实际上是按照顺序传递的。除非使用@Param注解去标识参数们。
备注:文章中使用SELECT *的做法不值得提倡,也建议大家自己定义ResultMap。