正在努力学习的小白袁 2024-07-23 18:22 采纳率: 90%
浏览 22

mybatis多对一映射陷入死循环

请看问题描述
首先我的数据表

img

img


对应的类:
user类

img

Pet类

img


mapper文件

img

img


xml文件

<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.mybatis.mapper.PetMapper">
    <resultMap id="queryPetByUserIdMap" type="Pet">
        <id property="id" column="id"/>
        <result property="nickname" column="nickname"/>
        <association property="user" column="user_id" select="com.mybatis.mapper.UserMapper.queryUserById"/>
    </resultMap>
    <select id="queryPetByUserId" resultMap="queryPetByUserIdMap">
        select * from mybatis_pet where user_id=#{id}
    </select>
</mapper>


<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.mybatis.mapper.UserMapper">

    <resultMap id="queryUserByIdMap" type="User">
        <id property="id" column="id"/>
        <result property="name" column="name"/>
        <collection property="pets" column="id" ofType="Pet" select="com.mybatis.mapper.PetMapper.queryPetByUserId"/>
    </resultMap>
    <select id="queryUserById" resultMap="queryUserByIdMap" >
        select * from mybatis_user where id=#{id}
    </select>
</mapper>


测试代码

    @Test
    public void test1(){
        User user = userMapper.queryUserById(1);
        System.out.println(user.getId()+"==="+user.getName());
        List<Pet> pets = user.getPets();
        for (Pet pet : pets) {
            System.out.println("================================");
            System.out.println(pet.getId()+"==="+pet.getNickname()+"===");
        }
    }

运行结果

img


疑问:当我调用userMapper.queryUserById方法的时候,会执行xml文件的sql语句,但因为有resultMap,会执行PetMapper.queryPetByUserId(),但是在PetMapper.Xml文件里面有association,又会继续调用UserMapper.queryUserById方法,而在这个queryUserById方法里面,又继续调用PetMapper.queryPetByUserId(),反反复复查询下去,不就是死循环吗?但是为什么运行的结果却不会出现栈溢出呢?同时我再debug的时候的结果是层层嵌套对象的,按理来说应该是递归的结果导致的才对。而且能正常运行出来!!

  • 写回答

3条回答 默认 最新

  • 阿里嘎多学长 2024-07-23 18:22
    关注

    以下内容由AIGC及阿里嘎多学长共同生成、有用望采纳:


    从您提供的信息来看,您遇到的问题主要是由于MyBatis的多对多映射配置不当导致的死循环。下面是针对您提出的问题的解决方案:

    1. 类和数据表映射问题

      • 根据您提供的类定义和数据表结构,User类和Pet类需要与mybatis_usermybatis_pet表进行映射。您需要确保类中的属性名称与数据库表的列名相对应。
    2. Mapper接口定义问题

      • UserMapperPetMapper接口中定义的方法看起来是正确的,它们分别提供了根据用户ID查询用户信息和根据用户ID查询宠物信息的方法。
    3. XML映射文件配置问题

      • 您在UserMapper.xml中使用了collection标签来加载用户的宠物列表,但是在PetMapper.xml中使用了association标签来加载宠物的用户信息。这是导致死循环的原因。您需要在PetMapper.xml中使用association标签,并通过select属性指定加载用户信息的SQL语句,而不是调用UserMapper的方法。
    4. 测试代码问题

      • 您的测试代码看起来是正确的,它应该能够验证User和Pet的关联关系是否正确加载。但是,由于死循环问题,测试代码可能无法正常执行。
    5. 死循环问题

      • 死循环的原因是在PetMapper.xml中使用了association标签的select属性来调用UserMapper的方法,这导致了无限递归。您需要更改PetMapper.xml中的配置,直接使用SQL语句来加载用户信息,而不是调用UserMapper的方法。
    6. toString方法问题

      • 死循环错误信息中提到toString方法抛出了StackOverflowError异常,这通常是由于toString方法中调用了对象自身的toString方法或者相互调用导致的。您需要检查User和Pet类的toString方法,确保它们不会相互调用。

    针对上述问题,您可以采取以下步骤进行修复:

    • 修改PetMapper.xml,使用SQL语句而不是调用UserMapper的方法来加载用户信息。
    • 检查并修改User和Pet类的toString方法,避免递归调用。
    • 重新运行测试代码,验证是否解决了死循环问题。

    以下是修改后的PetMapper.xml示例:

    <mapper namespace="com.mybatis.mapper.PetMapper">
        <resultMap id="queryPetByUserIdMap" type="Pet">
            <id property="id" column="id"/>
            <result property="nickname" column="nickname"/>
            <association property="user" javaType="User" column="user_id" select="selectUserByPet"/>
        </resultMap>
        <select id="queryPetByUserId" resultMap="queryPetByUserIdMap">
            select * from mybatis_pet where user_id=#{id}
        </select>
        <!-- 新增SQL语句来加载用户信息 -->
        <select id="selectUserByPet" resultType="User">
            select * from mybatis_user where id = #{user_id}
        </select>
    </mapper>
    

    请注意,您需要确保selectUserByPet的SQL语句能够正确执行,并且resultType与User类匹配。同时,确保User和Pet类的toString方法不会导致递归调用。

    评论 编辑记录

报告相同问题?

问题事件

  • 专家修改了标签 7月23日
  • 修改了问题 7月23日
  • 修改了问题 7月23日
  • 创建了问题 7月23日

悬赏问题

  • ¥15 verilog 非阻塞赋值下的移位拼接错误
  • ¥100 两个按钮控制一个LED
  • ¥15 用C语言写离散数学相关问题
  • ¥30 如何用python的GephiStreamer连接到gephi中,把Python和Gephi的具体操作过程都展示,重点回答Gephi软件的调试,以及如果代码的端口在浏览器中无法显示怎么处理
  • ¥15 ansys机翼建模肋参数
  • ¥15 Sumo软件无法运行
  • ¥15 如何在vscode里搭建stata的编辑环境?
  • ¥15 dify知识库创建问题
  • ¥15 如何用C#的chart画1000万个点不卡顿
  • ¥15 爬虫技术找到网上看过房源客户的电话