常见错误用法

select * from tbl where title like '%#{title}%'

这种写法, 会报以下类似错:

Error setting non null for parameter #5 with JdbcType null . Try setting a different JdbcType for this parameter or a different configuration property. Cause: java.sql.SQLException: Parameter index out of range (5 > number of parameters, which is 4).

正确用法

mybatis

<select id="selectBlogsLike" resultType="Blog">
  <bind name="pattern" value="'%' + _parameter.getTitle() + '%'" />
  SELECT * FROM BLOG
  WHERE title LIKE #{pattern}
</select>

Why ?

知其然, 更要知其所以然. 这让我们来从源码调试发现原因

这样子的写法

@Mapper
public interface DemoMapper {
    String getById(@Param("title") String title);
}
    <select id="getById" resultType="string">
      SELECT title from test_like WHERE title '%#{title}%';
    </select>

运行时, 发现它报了以下错误

Caused by: org.apache.ibatis.type.TypeException: Error setting non null for parameter #1 with JdbcType null . Try setting a different JdbcType for this parameter or a different configuration property. Cause: org.apache.ibatis.type.TypeException: Error setting non null for parameter #1 with JdbcType null . Try setting a different JdbcType for this parameter or a different configuration property. Cause: java.sql.SQLException: Parameter index out of range (1 > number of parameters, which is 0).
	at org.apache.ibatis.type.BaseTypeHandler.setParameter(BaseTypeHandler.java:55) ~[mybatis-3.4.5.jar:3.4.5]
	at org.apache.ibatis.scripting.defaults.DefaultParameterHandler.setParameters(DefaultParameterHandler.java:87) ~[mybatis-3.4.5.jar:3.4.5]
	... 45 common frames omitted
Caused by: org.apache.ibatis.type.TypeException: Error setting non null for parameter #1 with JdbcType null . Try setting a different JdbcType for this parameter or a different configuration property. Cause: java.sql.SQLException: Parameter index out of range (1 > number of parameters, which is 0).
	at org.apache.ibatis.type.BaseTypeHandler.setParameter(BaseTypeHandler.java:55) ~[mybatis-3.4.5.jar:3.4.5]
	at org.apache.ibatis.type.UnknownTypeHandler.setNonNullParameter(UnknownTypeHandler.java:45) ~[mybatis-3.4.5.jar:3.4.5]
	at org.apache.ibatis.type.BaseTypeHandler.setParameter(BaseTypeHandler.java:53) ~[mybatis-3.4.5.jar:3.4.5]
	... 46 common frames omitted
Caused by: java.sql.SQLException: Parameter index out of range (1 > number of parameters, which is 0).

img

可以看到, 预先的处理后, mybatis 将 '%#{title}%' 替换为了 '%?%' , 并且将我们的命名的参数保存在了一个 ParamMap 对象中.

img

到这里时, 可以看到 mybatis 准备将我们的 sql 字段, 用 parameterObject 对象来进行参数替换.

img

到这里时, 就准备正式将相应的参数的值设置到SQL语句中.

img img

最终问题

原来这并不关 MyBatis 的事, 这里到 jdbc 才开始报错的. 因为占位符 '%?%'%?% 是不同的, 前面的是有引号括住 ? , 后面一个是没引号括住的.

可以看到, 正确的占位符时, 它的SQL是这样子的

img

这………_