今天突然碰到这个错误,让我复习下mybatis 中 useGeneratedKeys 和 keyProperty 含义
nested exception is org.apache.ibatis.executor.ExecutorException: Error getting generated key or setting result to parameter object. Cause: org.apache.ibatis.executor.ExecutorException: Could not determine which parameter to assign generated keys to. Note that when there are multiple parameters, 'keyProperty' must include the parameter name (e.g. 'param.id'). Specified key properties are [id] and available parameters are [2]
MyBatis如何获取插入记录的自增长字段值:
第一步:
在Mybatis Mapper文件中添加属性useGeneratedKeys
和keyProperty
,其中keyProperty是Java对象的属性名!
<insert id="insert" parameterType="Spares"
useGeneratedKeys="true" keyProperty="id">
insert into spares(spares_id,spares_name,
spares_type_id,spares_spec)
values(#{id},#{name},#{typeId},#{spec})
</insert>
第二步:
Mybatis执行完插入语句后,自动将自增长值赋值给对象Spares的属性id。因此,可通过Spares对应的getter方法获取!
/**
* 新增备件
* @author hellostory
* @param spares
* @return
*/
@RequestMapping(value = "/insert")
@ResponseBody
public JsonResponse insert(Spares spares) {
int count = sparesService.insert(spares); //count>0 表示成功
System.out.println( "刚刚插入记录的主键自增长值为:" + spares.getId());
如果没有useGeneratedKeys="true"
和keyProperty="id"
,下面 insert 之后的 user.getId() 是无法获取 id 值
public void insert(User user) {
int count = userMapper.insert(user);
System.out.println("共插入" + count + "条记录!" + "\n刚刚插入记录的主键自增长值为:" + user.getId());
}
总结
useGeneratedKeys
的意思是向传入的Model赋值自增长id 。而keyProperty
表示将自增长id赋值给哪个字段。所以当传入两个参数时,会报如上错误;
可参照getAssignerForParamMap
源码:
private Entry<String, KeyAssigner> getAssignerForParamMap(Configuration config, ResultSetMetaData rsmd,
int columnPosition, Map<String, ?> paramMap, String keyProperty, String[] keyProperties, boolean omitParamName) {
//判断paramMap是否只有一个唯一key
boolean singleParam = paramMap.values().stream().distinct().count() == 1;
//获取keyProperty的.的位置
int firstDot = keyProperty.indexOf('.');
//如果是多个参数,但是keyProperty又不包含.,会抛出错误
if (firstDot == -1) {
if (singleParam) {
return getAssignerForSingleParam(config, rsmd, columnPosition, paramMap, keyProperty, omitParamName);
}
throw new ExecutorException("Could not determine which parameter to assign generated keys to. "
+ "Note that when there are multiple parameters, 'keyProperty' must include the parameter name (e.g. 'param.id'). "
+ "Specified key properties are " + ArrayUtil.toString(keyProperties) + " and available parameters are "
+ paramMap.keySet());
}
//多参数,需要截取keyProperty的.之前部分,去paramMap拿对应值
String paramName = keyProperty.substring(0, firstDot);
if (paramMap.containsKey(paramName)) {
String argParamName = omitParamName ? null : paramName;
String argKeyProperty = keyProperty.substring(firstDot + 1);
return entry(paramName, new KeyAssigner(config, rsmd, columnPosition, argParamName, argKeyProperty));
} else if (singleParam) {
return getAssignerForSingleParam(config, rsmd, columnPosition, paramMap, keyProperty, omitParamName);
} else {
throw new ExecutorException("Could not find parameter '" + paramName + "'. "
+ "Note that when there are multiple parameters, 'keyProperty' must include the parameter name (e.g. 'param.id'). "
+ "Specified key properties are " + ArrayUtil.toString(keyProperties) + " and available parameters are "
+ paramMap.keySet());
}
}