Mybatis(三)返回值四.注解配置

本文详细介绍了MyBatis框架中的两种结果映射方式:resultType和resultMap,解释了它们的区别及应用场景,包括如何使用注解进行配置,以及在复杂查询中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一. Mybatis返回值

   MyBatis中在查询进行select映射的时候,返回类型可以用resultType,也可以用resultMap,resultType是直接表示返回类型的,而resultMap则是对外部ResultMap的引用,但是resultType跟resultMap不能同时存在。

 

   在MyBatis进行查询映射时,其实查询出来的每一个属性都是放在一个对应的Map里面的,其中键是属性名,值则是其对应的值。

 

   ①当提供的返回类型属性是resultType时,MyBatis会将Map里面的键值对取出赋给resultType所指定的对象对应的属性。其实MyBatis的每一个查询映射的返回类型都是ResultMap,只是当提供的返回类型属性resultType的时候,MyBatis自动的给对应的值赋给resultType所指定对象的属性。

 

   ②当提供的返回类型是resultMap时,因为Map不能很好表示领域模型,就需要自己再进一步的把它转化为对应的对象,这常常在复杂查询中很有作用(association,Collection),

  

复制代码

<resultMap type="com.softjx.model.User" id="UserMap">
  <result column="t_id" property="id"/>
  <result column="t_username" property="username" />
  <result column="t_password" property="password"/>
</resultMap>


 <!-- 查询数据表中的所有记录,并封装User对象集合 -->
<select id="selectAll" resultMap="UserMap">
 select * from t_user
</select>

<!-- 根据id查询数据表中的一条记录,并封装User对象 -->
<select id="selectById"  resultMap="UserMap">
 select * from t_user where t_id=#{id};
</select>

//统计id>?记录数
    public int coutUser(Integer id);

//统计id>?记录数

<select id="coutUser" resultType="int">
 select count(*) from t_user where t_id>#{id};
</select>

复制代码

 

二. Mybatis注解配置

 

  Mybatis中使用注解,就不需要编写mapper.xml文件,直接在接口代码中使用注解。

 

 

  1、mybatis的全局配置文件要修改,指向接口文件路

  <mappers>        
         <mapper class="com.softjx.dao.UserMapper"/>         
      </mappers>

 

  2、不用编写mapper.xml文件,写接口,在接口中使用注解

 

  

复制代码

@Select("select t_id as id,t_username username,t_password as password from t_user")
    //@Select("select * from t_user")//不好自动填充javabean中的数据
    //@ResultType(User.class)//不写没有关系
    public List<User> selectAll();
    
    @Select("select t_id as id,t_username username,t_password as password from t_user  where t_id=#{id}")
    //@Select("select * from t_user where t_id=#{id}")//不好自动填充javabean中的数据
    //@ResultType(User.class)//不写没有关系
    public User selectById(int id);

    
    @Select("select t_id as id,t_username username,t_password as password from t_user where t_id > #{a} and t_username=#{b}")
    @ResultType(User.class)
    public List<User> selectByNameId(Map<String, Object> map);
    
    
    
    
    @Select("select t_id as id,t_username username,t_password as password from t_user where t_id > #{0} and t_username=#{1}")
    @ResultType(User.class)
    public List<User> selectByNameId1(Integer id,String ame);
    

    
    @Select("select t_id as id,t_username username,t_password as password from t_user where t_id > #{id} and t_username=#{name}")
    @ResultType(User.class)
    public List<User> selectByNameId2(@Param("id")Integer id,@Param("name")String name);
    
    

    
    @Select("select * from t_user")
    @Results({@Result(property="id",column="t_id")
             ,@Result(property="username",column="t_username")
             ,@Result(property="password",column="t_password")
             
            })
        public List<User> selectAllUsers();
    

    
    
    @Insert("insert into t_user (t_username,t_password) values (#{username},#{password})")
    public int insertUser(User user);
    

    @Update("update t_user set t_username=#{username},t_password=#{password} where t_id=#{id}")
    public int updateUser(User user);

    
    
    @Delete("delete from t_user where t_id=#{a}")
    public int deleteUser(int id);

        

复制代码

  3、编写测试类与以前一样,没有区别。

 

<think>好的,我现在需要帮助用户解决MyBatis中使用where in时出现的java.lang.UnsupportedOperationException异常。首先,我需要回忆一下这个异常通常是什么原因引起的。根据之前看到的引用内容,用户的问题可能与MyBatis返回的集合类型有关,特别是当使用不可变集合时,比如Arrays.asList()返回的列表,它不支持添加或删除操作,从而导致UnsupportedOperationException。 用户提到的是在使用where in时出现这个问题。通常,where in子句在MyBatis中是通过动态SQL的foreach标签来生成IN条件的。比如,用户可能传入一个列表作为参数,然后在XML映射文件中使用foreach遍历生成IN (item1, item2, ...)。这个时候,如果传入的集合是不可变的,可能在处理过程中尝试修改集合,从而抛出异常。 接下来,我需要查看用户提供的引用内容。引用[1]到[4]都提到了在MyBatis返回List类型时,如果resultType设置不正确,比如写成了java.util.List而不是具体的元素类型(如String或某个实体类),这可能导致MyBatis返回一个不可变的集合,例如当使用Arrays.asList()时。例如,引用[2]和[3]中的示例代码中的resultType被错误地设置为java.util.List,而正确的应该是集合中元素的类型,比如java.lang.String或者全限定类名。 但是用户现在的问题不是关于返回类型,而是在使用where in时出现的异常。这时候可能需要检查传入的参数类型是否正确。例如,如果用户传入的是一个不可变的集合(比如通过Arrays.asList()得到的List),当MyBatis在处理动态SQL,特别是foreach循环时,可能会尝试对这个集合进行操作,从而导致异常。 可能的解决方案包括: 1. 确保传入的集合参数是可变的,比如使用ArrayList而不是Arrays.asList()生成的列表。因为Arrays.asList()返回的是基于数组的固定大小列表,不支持添加或删除操作,而MyBatis可能在处理foreach时需要进行某些操作,导致异常。 2. 检查MyBatis映射文件中foreach标签的使用是否正确。比如,collection属性是否指定正确,如果是单个参数,可能需要使用@Param注解指定参数名,或者在XML中使用正确的参数名称。 3. 检查参数类型是否正确,确保传入的是一个List实例,而不是其他类型的集合,或者数组。例如,如果使用数组,可能需要转换为List。 另外,用户之前的引用内容中提到的resultType错误的问题,虽然用户当前的问题不是返回值,但可能需要提醒用户检查其他可能的配置错误,避免混淆。 例如,用户可能在映射文件中这样写: <select id="selectByIds" parameterType="list" resultType="com.example.Entity"> SELECT * FROM table WHERE id IN <foreach collection="list" item="id" open="(" separator="," close=")"> #{id} </foreach> </select> 如果传入的list参数是不可变的,比如使用Arrays.asList()创建的,那么当MyBatis处理时,是否会有问题?可能需要测试这种情况。例如,当MyBatis遍历这个列表时,是否会对列表进行修改操作?可能不会,但需要确认。 另外,可能用户传入的参数类型不是List,而是其他类型,导致MyBatis在处理foreach时出现问题,从而间接导致异常。例如,如果参数是数组,但collection属性错误地写成了"list"而不是"array",这可能导致MyBatis尝试转换为List时出错。 或者,当用户传入的参数是单个元素,而MyBatis尝试处理成集合时,可能引发问题。例如,当传入的列表是空的,或者参数绑定不正确,导致MyBatis内部处理时生成不可变的空集合,从而在后续操作中抛出异常。 总结可能的解决步骤: 1. 确认传入的集合参数是可变集合,如ArrayList,而不是由Arrays.asList()生成的不可变列表。 2. 检查映射文件中foreach标签的collection属性是否正确,确保引用了正确的参数名称,特别是当方法参数有多个时,需要使用@Param注解指定名称。 3. 检查参数类型是否正确,确保传入的是List类型,并且在XML中正确配置collection属性。 4. 验证MyBatis版本是否存在已知问题,考虑升级到最新版本。 例如,用户可能在代码中这样调用: List<Long> ids = Arrays.asList(1L, 2L, 3L); mapper.selectByIds(ids); 这里,Arrays.asList返回的是固定大小的列表,可能不可变。如果MyBatis在处理foreach时尝试修改这个列表(例如,添加元素,虽然这似乎不太可能),就会导致异常。或者,可能在参数传递过程中,MyBatis内部对集合进行了某些操作,如转换为其他类型,导致问题。这时候,将参数改为new ArrayList<>(Arrays.asList(1L,2L,3L))可能会解决。 另一个可能的错误是,在映射文件中,foreach的collection属性指定错误。例如,如果方法参数没有使用@Param注解,而参数是单个集合,则应该使用collection="list"或collection="collection"。例如: public interface Mapper { List<Entity> selectByIds(@Param("ids") List<Long> ids); } 然后在XML中,使用collection="ids"。如果未使用@Param,则默认的参数名可能是"list"或"collection"(取决于MyBatis版本),或者参数索引如"param1"。如果collection属性写错,可能导致MyBatis无法找到正确的集合,进而抛出异常。 另外,用户可能在映射文件中错误地配置了参数类型,导致MyBatis在解析参数时出现错误,从而引发异常。 综上所述,解决步骤应首先检查传入的集合是否为可变集合,然后检查foreach配置是否正确,参数名称是否匹配,以及可能的参数类型问题。</think>### MyBatis中使用WHERE IN导致UnsupportedOperationException的解决方案 当MyBatis的`WHERE IN`子句与`java.lang.UnsupportedOperationException`异常关联时,通常与**参数集合的不可变性**或**XML配置错误**有关。以下是逐步排查与解决方法: --- #### 1. 检查传入的集合类型 **问题根源**: 如果使用`Arrays.asList()`生成的集合作为参数传递给`WHERE IN`,会导致异常。因为`Arrays.asList()`返回的是**固定大小的列表**(基于数组实现),无法支持动态修改操作。当MyBatis内部尝试操作此集合时(如遍历或转换),会触发异常。 **解决方案**: 将不可变集合转换为可变的`ArrayList`: ```java // 错误写法 List<Long> ids = Arrays.asList(1L, 2L, 3L); // 正确写法 List<Long> ids = new ArrayList<>(Arrays.asList(1L, 2L, 3L)); ``` --- #### 2. 验证XML映射文件的foreach配置 **关键配置项**: 确保`<foreach>`标签的`collection`属性与接口方法中定义的参数名称一致。若未通过`@Param`指定名称,默认使用`list`或`collection`(取决于MyBatis版本)。 **示例代码**: ```xml <select id="selectByIds" resultType="com.example.Entity"> SELECT * FROM table WHERE id IN <foreach collection="ids" item="id" open="(" separator="," close=")"> #{id} </foreach> </select> ``` **接口方法定义**(使用`@Param`注解): ```java List<Entity> selectByIds(@Param("ids") List<Long> ids); ``` --- #### 3. 检查参数绑定逻辑 **常见错误场景**: - 参数未正确封装为Map或对象 - 集合参数未通过`@Param`命名 - 方法参数类型不匹配(如传递数组而非List) **修正方法**: 若方法有多个参数,必须通过`@Param`显式命名: ```java List<Entity> selectByCondition( @Param("ids") List<Long> ids, @Param("status") Integer status ); ``` --- #### 4. 验证MyBatis版本 **潜在问题**: 旧版本MyBatis可能对集合处理存在兼容性问题。建议升级至**最新稳定版本**,确保已知Bug已修复。 --- #### 5. 完整示例 **Mapper接口**: ```java public interface UserMapper { List<User> findUsersByIds(@Param("idList") List<Long> idList); } ``` **XML映射文件**: ```xml <select id="findUsersByIds" resultType="User"> SELECT * FROM users WHERE id IN <foreach collection="idList" item="id" open="(" separator="," close=")"> #{id} </foreach> </select> ``` **调用代码**: ```java // 使用可变集合 List<Long> ids = new ArrayList<>(Arrays.asList(1001L, 1002L, 1003L)); List<User> users = userMapper.findUsersByIds(ids); ``` --- ### 总结 此异常通常由以下原因导致: 1. 参数集合不可变(如`Arrays.asList()`生成的列表) 2. `<foreach>`标签的`collection`属性与参数名称不匹配 3. MyBatis版本过旧 通过改用可变集合、修正XML配置并升级框架版本,可彻底解决问题[^1][^2]。 ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值