Article Directory
I encountered an error encountered in Mybatis plus paging query at work today, indicating that the parameter is not bound, so record it now. The following data are all MOCK information
0 gives the error scenario first
java entity entity class
用 user 代替实体类信息
@Data
class User {
private Long id;
private String name;
private String agx;
private Integer age;
}
用 condition 代替查询信息
@Data
class Condition {
private Long id;
private String name;
private String agx;
private Integer age;
}
java mapper interface methods
List<User> queryByCondition(Condition condition);
IPage<User> queryByCondition(Page<?> page, Condition condition);
The mapper.xml information corresponding to the Java mapper
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="please ignore">
<resultMap id="Base_Column_result_map"
type="User">
<id column="id" property="id"/>
<result column="name" property="name"/>
<result column="agx" property="agx"/>
<result column="age" property="age"/>
</resultMap>
<sql id="Base_Column_select_map">
id, name, agx, age
</sql>
<select id="queryByCondition"
parameterType="Condition"
resultMap="Base_Column_result_map">
SELECT
<include refid="Base_Column_select_map"/>
FROM
t_wms_inv_inventory_asset
<where>
<if test="id != null">
AND id = #{id}
</if>
<if test="name != null">
AND name = #{name}
</if>
<if test="agx != null">
AND agx = #{agx}
</if>
<if test="age != null">
AND age = #{age}
</if>
</where>
</select>
</mapper>
exception information
invoke method = queryByCondition exception
org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.binding.BindingException: Parameter 'id' not found. Available parameters are [arg1, arg0, param1, param2]
at org.mybatis.spring.MyBatisExceptionTranslator.translateExceptionIfPossible(MyBatisExceptionTranslator.java:78)
at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:440)
at com.sun.proxy.$Proxy105.selectList(Unknown Source)
at org.mybatis.spring.SqlSessionTemplate.selectList(SqlSessionTemplate.java:223)
at com.baomidou.mybatisplus.core.override.MybatisMapperMethod.executeForIPage(MybatisMapperMethod.java:122)
at com.baomidou.mybatisplus.core.override.MybatisMapperMethod.execute(MybatisMapperMethod.java:86)
at com.baomidou.mybatisplus.core.override.MybatisMapperProxy$PlainMethodInvoker.invoke(MybatisMapperProxy.java:148)
at com.baomidou.mybatisplus.core.override.MybatisMapperProxy.invoke(MybatisMapperProxy.java:89)
at com.sun.proxy.$Proxy154.queryInventoryAssets(Unknown Source)
... 省略部分冗余信息
Caused by: org.apache.ibatis.binding.BindingException: Parameter 'id' not found. Available parameters are [arg1, arg0, param1, param2]
at org.apache.ibatis.binding.MapperMethod$ParamMap.get(MapperMethod.java:212)
at org.apache.ibatis.scripting.xmltags.DynamicContext$ContextAccessor.getProperty(DynamicContext.java:120)
at org.apache.ibatis.ognl.OgnlRuntime.getProperty(OgnlRuntime.java:2719)
at org.apache.ibatis.ognl.ASTProperty.getValueBody(ASTProperty.java:114)
at org.apache.ibatis.ognl.SimpleNode.evaluateGetValueBody(SimpleNode.java:212)
at org.apache.ibatis.ognl.SimpleNode.getValue(SimpleNode.java:258)
at org.apache.ibatis.ognl.ASTNotEq.getValueBody(ASTNotEq.java:50)
at org.apache.ibatis.ognl.SimpleNode.evaluateGetValueBody(SimpleNode.java:212)
at org.apache.ibatis.ognl.SimpleNode.getValue(SimpleNode.java:258)
at org.apache.ibatis.ognl.ASTAnd.getValueBody(ASTAnd.java:61)
at org.apache.ibatis.ognl.SimpleNode.evaluateGetValueBody(SimpleNode.java:212)
at org.apache.ibatis.ognl.SimpleNode.getValue(SimpleNode.java:258)
at org.apache.ibatis.ognl.Ognl.getValue(Ognl.java:493)
at org.apache.ibatis.ognl.Ognl.getValue(Ognl.java:457)
at org.apache.ibatis.scripting.xmltags.OgnlCache.getValue(OgnlCache.java:46)
at org.apache.ibatis.scripting.xmltags.ExpressionEvaluator.evaluateBoolean(ExpressionEvaluator.java:32)
at org.apache.ibatis.scripting.xmltags.IfSqlNode.apply(IfSqlNode.java:34)
at org.apache.ibatis.scripting.xmltags.MixedSqlNode.lambda$apply$0(MixedSqlNode.java:32)
at java.util.ArrayList.forEach(ArrayList.java:1257)
at org.apache.ibatis.scripting.xmltags.MixedSqlNode.apply(MixedSqlNode.java:32)
at org.apache.ibatis.scripting.xmltags.TrimSqlNode.apply(TrimSqlNode.java:55)
at org.apache.ibatis.scripting.xmltags.MixedSqlNode.lambda$apply$0(MixedSqlNode.java:32)
at java.util.ArrayList.forEach(ArrayList.java:1257)
at org.apache.ibatis.scripting.xmltags.MixedSqlNode.apply(MixedSqlNode.java:32)
at org.apache.ibatis.scripting.xmltags.DynamicSqlSource.getBoundSql(DynamicSqlSource.java:39)
at org.apache.ibatis.mapping.MappedStatement.getBoundSql(MappedStatement.java:297)
at com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor.intercept(MybatisPlusInterceptor.java:69)
at org.apache.ibatis.plugin.Plugin.invoke(Plugin.java:61)
at com.sun.proxy.$Proxy434.query(Unknown Source)
at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:147)
at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:140)
at sun.reflect.GeneratedMethodAccessor351.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:426)
... 76 common frames omitted
1 solution
step1: Add named parameters to the mapper interface method, as follows:
List<User> queryByCondition(@Param("condition") Condition condition);
IPage<User> queryByCondition(Page<?> page,@Param("condition") Condition condition);
tip: Page 参数不要加 具名 指示
step2: Modify the query information of mapper.xml, and add named restrictions
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="please ignore">
<resultMap id="Base_Column_result_map"
type="User">
<id column="id" property="id"/>
<result column="name" property="name"/>
<result column="agx" property="agx"/>
<result column="age" property="age"/>
</resultMap>
<sql id="Base_Column_select_map">
id, name, agx, age
</sql>
<select id="queryByCondition"
parameterType="Condition"
resultMap="Base_Column_result_map">
SELECT
<include refid="Base_Column_select_map"/>
FROM
t_wms_inv_inventory_asset
<where>
<if test="condition.id != null">
AND id = #{condition.id}
</if>
<if test="condition.name != null">
AND name = #{condition.name}
</if>
<if test="condition.agx != null">
AND agx = #{condition.agx}
</if>
<if test="condition.age != null">
AND age = #{condition.age}
</if>
</where>
</select>
</mapper>
So far, the above error reporting problem has been completely solved, but out of
记录者
qualified status, the reason why the error is reported is tracked and displayed, and interested friends can take a look.
2 abnormal cause
mybatis plus [or mybtais] will generate a proxy class object for each mapper interface, and use the proxy class object to realize call recognition and assemble SQL, as shown in the figure below: Then
call the proxy class proxy interface to find a suitable executor, So as to parse and analyze SQL statements and xml conditional statements, as follows: The
key code inside the executor is shown in the figure:
if the form of Page + mapper is used as the parameter of the execution method, then it will eventually be located here:
enter the inside of executeForPage , you will find the following code:
In fact, the execution of paging, the underlying call is the selectList method of sqlSession [This also shows from the side, you cannot rewrite the selectList method of BaseMapper provided by mybatis plus, because there will be errors here]. Among them commnad.getName()
, the method obtains the interface method 全限定类名和路径
, param
which is the execution parameter of the method, that is, page
and condition
.
In the end, there will be an interceptor that intercepts the execution of the proxy method. This is the step for identifying and parsing parameters. Enter the selectList method, Debug into and you can find it. When you come here: step by step, you will eventually find out that when you come here
, That is, where the conditional node
is parsed : If node. To limit the class name, the param in the context does not recognize the id information, but only the poge and condition information.