使用myBatis调用存储过程的返回值,提示错误信息:
org.apache.ibatis.binding.BindingException: Mapper method 'com.xxxx.other.dao.MyDao.getNo attempted to return null from a method with a primitive return type (int).
先查mysql监控语句,发现存储过程调用正常,也得到了返回值,继续查
对应的文件
存储过程:
CREATE PROCEDURE `Get_Table_Flow_No`(IN `输入表名` VARCHAR(100), IN `待取数` INT, OUT `输出要取的最大流水号` INT) BEGIN DECLARE `willRetNo` INT; SET `输出要取的最大流水号` = 0 ; SELECT 字段_已取最大流水号 INTO `willRetNo` FROM 流水号保存表 WHERE 字段_表名=`输入表名` for UPDATE; IF `willRetNo` IS NULL THEN SET `willRetNo` = `待取数` ; INSERT INTO `流水号保存表` (字段_表名,字段_已取最大流水号,字段_上次获取时间) VALUES (`输入表名`, `willRetNo`, NOW()); ELSE SET `willRetNo` = `willRetNo` + `待取数` ; UPDATE `流水号保存表` SET 字段_已取最大流水号 = `willRetNo` , 字段_上次获取时间 = NOW() WHERE 字段_表名=`输入表名` ; END IF; SET `输出要取的最大流水号` = `willRetNo`; END
MyDao.xml
<?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="com.xxxx.other.dao.MyDao"> <parameterMap type="java.util.Map" id = "FlowNoMap"> <parameter property="输入表名" mode="IN" jdbcType="VARCHAR"/> <parameter property="待取数" mode="IN" jdbcType="INTEGER"/> <parameter property="返回最大数值" mode="OUT" jdbcType="INTEGER"/> </parameterMap> <select id="getFlowNo" parameterMap="FlowNoMap" statementType="CALLABLE"> <if test="_databaseId == 'mysql'"> call Get_Table_Flow_No(#{输入表名 ,jdbcType=VARCHAR,mode=IN},#{待取数,jdbcType=INTEGER,mode=IN},#{返回最大数值 ,jdbcType=INTEGER,mode=OUT}); </if> <if test="_databaseId == 'sqlserver'"></if> </select> </mapper>
MyDao.java
package com.xxxx.other.dao; import org.apache.ibatis.annotations.Param; import org.springframework.dao.DataAccessException; import java.util.List; import java.util.Map; public interface MyDao { int getNo(Map<String, Object> parameterMap) throws DataAccessException; }
错误信息出在:
org/apache/ibatis/binding/MapperMethod.java 方法 execute 中
if (result == null && method.getReturnType().isPrimitive() && !method.returnsVoid()) { throw new BindingException("Mapper method '" + command.getName() + " attempted to return null from a method with a primitive return type (" + method.getReturnType() + ")."); }
因为result 为 null,所以抛出了异常,往上推,同文件中
else if (SqlCommandType.SELECT == command.getType()) {
if (method.returnsVoid() && method.hasResultHandler()) {
executeWithResultHandler(sqlSession, args);
result = null;
} else if (method.returnsMany()) {
result = executeForMany(sqlSession, args);
} else if (method.returnsMap()) {
result = executeForMap(sqlSession, args);
} else {
Object param = method.convertArgsToSqlCommandParam(args);
result = sqlSession.selectOne(command.getName(), param);
}
}
调用的是最后一个条件:
Object param = method.convertArgsToSqlCommandParam(args); result = sqlSession.selectOne(command.getName(), param);
调用的存储过程中,只是把值通过输出参数返回出来,没提供select语句,所以result为空,但param中有对"返回最大数值"取到值
再返回报错的地方,看到有验证条件: !method.returnsVoid() ,实际在myDao.xml中是没有返回的,查询 MyDao.java,
接口中有返回值: int getNo(Map<String, Object> parameterMap) throws DataAccessException;
把 int 调整为 void, 程序运行正常,通过 parameterMap 取到了最大数