Mybatis中传参包There is no getter for property named 'XXX' in 'class java.lang.String'

时间:2022-08-08 17:04:24

一、发现问题

<select id="queryStudentByNum" resultType="student" parameterType="string">  

select num,name,phone from student  
<where> 
<if test = " num!=null and num!='' ">
AND num = #{num}
</if>
</where>
</select> 
Mybatis查询传入一个字符串传参数,报There is no getter for property named 'num' in 'class java.lang.String'。


二、解决问题

<select id="queryStudentByNum" resultType="student" parameterType="string">  

select num,name,phone from student  
<where> 
<if test = " _parameter!=null and_parameter!='' ">
AND num = #{_parameter}
</if>
</where>
</select>
无论参数名,都要改成"_parameter"。


三、原因分析

Mybatis默认采用ONGL解析参数,所以会自动采用对象树的形式取string.num值,引起报错。也可以public List methodName(@Param(value="num") String num)的方法说明参数值


参考博客:

http://blog.sina.com.cn/s/blog_86e49b8f010191hw.html

http://txin0814.iteye.com/blog/1533645

[java] view plaincopy
  1. 在类DynamicSqlSource   
  2. 方法   
  3. public BoundSql getBoundSql(Object parameterObject) {   
  4.     DynamicContext context = new DynamicContext(configuration, parameterObject);   
  5.     rootSqlNode.apply(context);   
  6.     SqlSourceBuilder sqlSourceParser = new SqlSourceBuilder(configuration);   
  7.     Class<?> parameterType = parameterObject == null ? Object.class : parameterObject.getClass();   
  8.     SqlSource sqlSource = sqlSourceParser.parse(context.getSql(), parameterType);   
  9.     BoundSql boundSql = sqlSource.getBoundSql(parameterObject);   
  10.     for (Map.Entry<String, Object> entry : context.getBindings().entrySet()) {   
  11.       boundSql.setAdditionalParameter(entry.getKey(), entry.getValue());   
  12.     }   
  13.     return boundSql;   
  14.   }   
  15. 第一行DynamicContext context = new DynamicContext(configuration, parameterObject);   
  16. 这句话是根据配置,sql语句,以及参数,来生成context。生成的context会会加入到ognl的contxt,因此在我们的sql访问#{_parameter},只要你插入参数,就一定可以找到我们传入的这个参数,而不用管它是什么类型   
  17.   
  18. 进入后可以看到   
  19. public DynamicContext(Configuration configuration, Object parameterObject) {   
  20.     if (parameterObject != null && !(parameterObject instanceof Map)) {   
  21.       MetaObject metaObject = configuration.newMetaObject(parameterObject);   
  22.       bindings = new ContextMap(metaObject);   
  23.     } else {   
  24.       bindings = new ContextMap(null);   
  25.     }   
  26.     bindings.put(PARAMETER_OBJECT_KEY, parameterObject);   
  27.   }   
  28. 1.bindings.put(PARAMETER_OBJECT_KEY, parameterObject);   
  29. 这里的PARAMETER_OBJECT_KEY = _parameter;   
  30. 因此在我们的sql中,类似于   
  31. <if test="_parameter != null" >   
  32.       <include refid="Example_Where_Clause" />   
  33.     </if>   
  34. 是没有问题的。   
  35.   
  36. 随后它会将这个传入的参数对象,根据它的类型,活得它可以得到的表达式。   
  37. if (object instanceof ObjectWrapper) {   
  38.       this.objectWrapper = (ObjectWrapper) object;   
  39.     } else if (objectWrapperFactory.hasWrapperFor(object)) {   
  40.       this.objectWrapper = objectWrapperFactory.getWrapperFor(this, object);   
  41.     } else if (object instanceof Map) {   
  42.       this.objectWrapper = new MapWrapper(this, (Map) object);   
  43.     } else {   
  44.       this.objectWrapper = new BeanWrapper(this, object);   
  45.     }   
  46.   
  47. 传入的是bean,BeanWrapper这个处理器会获取这个传入的参数的所有的get方法,并获取get方法后面的Xxx,如getName,就是name   
  48.   
  49. 多个参数   
  50. 我们可能会碰到多个参数作为参数的情况。   
  51. 如   
  52. public MessagegetMessages(String id, String messageType);   
  53.   
  54. 但ibatis只接受一个参数。   
  55. 这个时候可以使用javabean作为参数传递,或者使用Map作为参数传递。如   
  56. <select id="getMessages" parameterType="java.util.Map"   
  57. resultType="com.liyixing.ibatis.model.Message" >   
  58. SELECT *   
  59. FROM message WHERE ID = #{id} AND MESSAGE_TYPE = #{messageType}   
  60. </select>   
  61.   
  62. Map<String, Object> params = new HashMap<String, Object>();   
  63.   
  64. params.put("id"1);   
  65. params.put("messageType"1);   
  66. List<Message> messages = messageDao.getMessages(params);   
  67.   
  68. 因为ibatis使用OGNL作为表达式的。它把参数作为root,因为ognl的root只有一个。所以ibatis只能支持一个参数。