Could not find result map java.lang.Integer at org.apache.ibatis.builder.MapperBuilderAssistant.get

这篇博客讨论了一种常见的编程错误,即在mapper.xml文件中将Integer类型的字段错误地配置为了resultMap。正确做法应将类型设置为resultType,而非resultMap。博主详细解释了两者的区别,并提供了修正此问题的步骤,帮助开发者避免此类配置误区。

此错误是你的mapper.xml文件中将Integer 设置成了resultMap类型,应该是resultType

 


<think> 我们再次遇到了这个异常:`java.lang.IllegalArgumentException: Result Maps collection does not contain value for java.lang.String`。这个异常在MyBatis中通常表示映射配置有问题。下面我将详细解释原因和解决方法。 ### 错误原因分析 1. **返回类型配置错误**:在MyBatis的映射文件(XML)中,`<select>`、`<insert>`、`<update>`或`<delete>`标签的`resultType`或`resultMap`属性配置不正确。当返回类型被指定为`java.lang.String`(或其它简单类型)时,MyBatis会尝试在结果映射集合中查找对应的结果映射(ResultMap)。但是,MyBatis并没有为简单类型(如String、Integer等)预定义结果映射,因此会抛出此异常。 2. **实际SQL返回结果与声明返回类型不匹配**: - 如果Mapper接口中声明的方法返回类型是`String`(或者其他简单类型),那么SQL查询应该只返回一列(且一行)。如果SQL查询返回了多列,MyBatis无法将多列结果映射到单个简单类型上。 - 或者,如果SQL查询返回多行,但方法返回类型是单个简单类型(如`String`),则也会出错(除非使用聚合函数确保只返回一行一列)。 3. **使用了`resultMap`属性但未正确定义**:如果在映射文件中指定了一个`resultMap`属性,但是该`resultMap`并没有在配置文件中定义,或者名字写错了。 4. **动态SQL拼接错误**:在动态SQL中(如`<foreach>`标签)没有正确设置分隔符(如`separator=","`),导致SQL语句语法错误。但是,这种情况下通常会抛出SQL语法异常,而不是这个结果映射异常。 ### 解决方法 1. **修正返回类型**: - 如果SQL返回多个列,那么应该使用一个Java Bean(POJO)或者Map来接收结果。 - 如果SQL只返回一列,那么可以将结果类型指定为简单类型(如`java.lang.String`)。 2. **检查映射文件中的`resultType`或`resultMap`配置**: - 确保`resultType`的值是合法的全限定类名,或者MyBatis内置的别名(如`string`、`int`等)。 - 确保`resultMap`的值是一个已经定义好的`resultMap`的id。 3. **检查Mapper接口方法返回类型**:确保Mapper接口中声明的方法返回类型与映射文件中配置的结果类型匹配。 4. **检查SQL语句**:确保SQL语句返回的数据结构(列数、行数)与方法返回类型匹配。 ### 代码示例 **错误示例**: Mapper接口: ```java public interface UserMapper { String getUserNameById(Long id); } ``` 映射文件: ```xml <select id="getUserNameById" resultType="java.lang.String"> SELECT id, name FROM user WHERE id = #{id} </select> ``` 上面的SQL返回了两列(id和name),但是方法返回类型是`String`,这会导致异常。 **修正方法1**:修改SQL只返回一列 ```xml <select id="getUserNameById" resultType="string"> SELECT name FROM user WHERE id = #{id} </select> ``` **修正方法2**:修改返回类型为POJO 如果我们需要返回多个字段,那么应该使用一个POJO: ```java public class User { private Long id; private String name; // getters and setters } ``` Mapper接口修改为: ```java User getUserNameById(Long id); ``` 映射文件: ```xml <select id="getUserNameById" resultType="com.example.User"> SELECT id, name FROM user WHERE id = #{id} </select> ``` ### 特别说明:使用`resultMap`的情况 如果使用了`resultMap`,确保已经定义: ```xml <resultMap id="userResultMap" type="com.example.User"> <id property="id" column="id"/> <result property="name" column="name"/> </resultMap> <select id="getUserById" resultMap="userResultMap"> SELECT id, name FROM user WHERE id = #{id} </select> ``` ### 总结原因表格 | 原因 | 解决方法 | |------|----------| | 返回类型为简单类型(如String)但SQL返回多列 | 修改SQL只返回一列,或者修改返回类型为POJO | | 映射文件中使用了未定义的`resultMap` | 检查`resultMap`的id是否正确,或者定义该`resultMap` | | `resultType`写错了 | 检查`resultType`的拼写,使用全限定类名或MyBatis内置别名 | | SQL返回多行,但方法返回单个简单类型 | 确保SQL只返回一行(例如通过主键查询)或修改返回类型为集合(如`List<String>`) | §§相关问题§§: 1. MyBatis中`resultType`和`resultMap`有什么区别? 2. 在MyBatis中,如何映射查询结果到Java对象? 3. 当MyBatis的SQL查询返回多个结果集时,如何处理? 4. MyBatis如何自动映射数据库字段到Java对象的属性? </think> ### 错误原因分析 `java.lang.IllegalArgumentException: Result Maps collection does not contain value for java.lang.String` 错误的核心原因是 **MyBatis 无法找到适合 `java.lang.String` 类型的结果映射配置**。以下是具体原因分解: 1. **返回类型配置错误** Mapper 接口声明了返回 `String` 类型,但 XML 映射文件中: - 缺少 `resultType` 或 `resultMap` 属性 - 错误的 `resultType="java.lang.String"` 配置(当 SQL 实际返回多列时) 2. **结果映射缺失** - 当返回类型为简单类型(如 String)时,SQL 必须只返回**单列数据** - 如果 SQL 返回多列数据,必须使用 `resultMap` 或自定义 DTO 接收 3. **MyBatis 内部映射机制** 从堆栈可以看出错误发生在 MyBatis 结果映射处理流程: ```diff at org.apache.ibatis.session.Configuration$StrictMap.get(Configuration.java:1054) at org.apache.ibatis.session.Configuration.getResultMap(Configuration.java:763) at org.apache.ibatis.builder.MapperBuilderAssistant.getStatementResultMaps(...) ``` - MyBatis 会尝试从配置中获取 `java.lang.String` 对应的结果映射 - 但 MyBatis **不为简单类型预定义结果映射** --- ### 解决方法 #### 方案一:修正返回类型(推荐) 当 SQL 返回多列数据时,使用 DTO 对象接收: ```java // Mapper 接口 List<UserDTO> findUsers(); // DTO 类 public class UserDTO { private String name; private Integer age; // getters/setters } ``` XML 配置: ```xml <select id="findUsers" resultType="com.example.UserDTO"> SELECT name, age FROM users </select> ``` #### 方案二:确保只返回单列(当确实需要 String 时) ```xml <select id="findUserName" resultType="string"> SELECT name FROM users <!-- 只返回单列 --> </select> ``` #### 方案三:正确使用 resultMap 定义显式结果映射: ```xml <resultMap id="stringResult" type="string"> <result property="" column="user_name"/> </resultMap> <select id="findUserName" resultMap="stringResult"> SELECT user_name FROM users </select> ``` --- ### 错误重现示例 ```java // 错误Mapper接口声明 public interface UserMapper { String findUserNameAndAge(@Param("id") Integer id); } ``` ```xml <!-- 错误XML配置 --> <select id="findUserNameAndAge"> SELECT name, age FROM users WHERE id = #{id} </select> ``` **执行结果**: 当调用 `findUserNameAndAge()` 时,MyBatis 尝试将两列数据映射到单个 String 对象,导致: ``` Result Maps collection does not contain value for java.lang.String ``` --- ### 根本原因总结 | 错误根源 | 说明 | |---------|------| | 类型声明冲突 | 接口声明返回 String,但 SQL 返回多列 | | 结果映射缺失 | 缺少 `resultType` 或 `resultMap` 配置 | | 无效的简单类型映射 | MyBatis 无法自动映射多列到 String | | XML 配置不完整 | 未指定任何结果映射策略 |
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值