• 解决 mybatis 中相互关联的两种表数据在返回前端时一直循环查询,直到StackOverFlow报错


    原代码设计:

    一个用户有多个账户,是一对多的关系,用Collection集合关联;一个账户独属于一个用户,是一对一的关系,用association来关联;

    UserMapper.xml

    <mapper namespace="com.xuetu.springboot.mapper.UserMapper">
    
        <!-- 定义User的resultMap-->
        <resultMap id="userMap" type="user">
            <id property="id" column="id"></id>
            <result property="username" column="username"></result>
            <result property="address" column="address"></result>
            <result property="sex" column="sex"></result>
            <result property="birthday" column="birthday"></result>
            <!-- 配置user对象中accounts集合的映射 -->
            <collection property="accounts" ofType="account"
                        select="com.xuetu.springboot.mapper.AccountMapper.findAccountByUid"
                        column="id"
                        />
        </resultMap>
    
        <!-- 查询所有 -->
        <select id="findAll" resultMap="userMap">
            select * from user
        </select>
    
        <!-- 根据id查询用户 -->
        <select id="findById" parameterType="INT" resultMap="userMap">
            select * from user where id = #{uid}
        </select>
    

      AccountMapper.xml

    <mapper namespace="com.xuetu.springboot.mapper.AccountMapper">
        <resultMap id="accountMap" type="account">
            <id property="id" column="id" />
            <result property="uid" column="uid" />
            <result property="money" column="money" />
    
            <association property="user" column="uid"
                         select="com.xuetu.springboot.mapper.UserMapper.findById"
                         />
        </resultMap>
    
        <select id="findAll" resultMap="accountMap">
            select * from account;
        </select>
    
        <select id="findAccountByUid" resultMap="accountMap" parameterType="INT">
            select * from account where uid = #{uid}
        </select>
    

      

    问题发现:

    使用懒加载的情况下,如果仅仅是在controller 中操作一些数据,不把数据返回前端,那么没有问题,但是如果需要把数据集合变成JSON格式 返回给前端就会无限循环的进行SQL语句的查询,因为collection中select 寻找的是对象,这个对象又进行一对一关联查询,获得的对象又进行一对多关联查询,以此循环往复,最终导致内存溢出。

    希望的效果是:如果返回用户集合,这个集合中各个用户的只有一个账户列表(一对多),账户对象一对一指向为空

    例如下列数据:

    [{"id":41,"username":"老王","address":"北京","sex":"男","birthday":"2018-02-27T17:47:08.000+0000","accounts":[{"id":1,"uid":41,"money":1000.0,"user":null},
    {"id":3,"uid":41,"money":3000.0,"user":null}]},
    {"id":42,"username":"小二王","address":"北京金燕龙","sex":"女","birthday":"2018-03-02T15:09:37.000+0000","accounts":[]},
    {"id":43,"username":"小二九","address":"北京金燕龙","sex":"女","birthday":"2018-03-04T11:34:34.000+0000","accounts":[{"id":2,"uid":43,"money":2000.0,"user":null}]},
    {"id":45,"username":"传智播客","address":"北京金燕龙","sex":"男","birthday":"2018-03-04T12:04:06.000+0000","accounts":[]},
    {"id":46,"username":"老久","address":"北京","sex":"女","birthday":"2018-03-07T17:37:26.000+0000","accounts":[]},
    {"id":48,"username":"小马宝莉","address":"北京修正","sex":"女","birthday":"2018-03-08T11:44:00.000+0000","accounts":[]},
    {"id":51,"username":"李四","address":"广西南宁市","sex":"男","birthday":"2019-07-21T06:29:22.000+0000","accounts":[]},
    {"id":52,"username":"王五","address":"广西桂林市","sex":"男","birthday":"2019-07-20T08:19:50.000+0000","accounts":[]}]

    解决办法:新增一个单独指向不关联的方法
    UserMapper中
    <!-- 定义User的resultMap--> <resultMap id="userMap" type="user"> <id property="id" column="id"></id> <result property="username" column="username"></result> <result property="address" column="address"></result> <result property="sex" column="sex"></result> <result property="birthday" column="birthday"></result> <!-- 配置user对象中accounts集合的映射 --> <collection property="accounts" ofType="account" select="com.xuetu.springboot.mapper.AccountMapper.findAccountByUidNoRel" column="id" /> </resultMap>
    AccountMapper中: <!--返回的对象是Account普通对象,而不是原来的accountMap-->
    <select id="findAccountByUidNoRel" resultType="account" parameterType="INT">
    select * from account where uid = #{uid}
    </select>

    UserMapper.java接口中新增方法findByIdNoRel
    @Repository
    public interface UserMapper {
    /**
    * 查询所有用户,同时获取到用户下所有账户的信息
    * @return
    */
    List<User> findAll();
    // /**
    // * 根据id查询用户信息
    // * @param userId
    // * @return
    // */
    User findById(Integer userId);

    User findByIdNoRel(Integer userId);

      这样返回的数据就不会一直相互请求关联下去了,这里需要忽略序列化的属性,使用@JsonIgnore,因为一对一指向为空

    @JsonIgnoreProperties(value = {"handler"})
    public class User implements Serializable {
    private Integer id;
    private String username;
    private String address;
    ......

      最终可以将查询用户的结果集json格式 返回给前端结果:

    [{"id":41,"username":"老王","address":"北京","sex":"男","birthday":"2018-02-27T17:47:08.000+0000","accounts":[{"id":1,"uid":41,"money":1000.0,"user":null},
    {"id":3,"uid":41,"money":3000.0,"user":null}]},
    {"id":42,"username":"小二王","address":"北京金燕龙","sex":"女","birthday":"2018-03-02T15:09:37.000+0000","accounts":[]},
    {"id":43,"username":"小二九","address":"北京金燕龙","sex":"女","birthday":"2018-03-04T11:34:34.000+0000","accounts":[{"id":2,"uid":43,"money":2000.0,"user":null}]},
    {"id":45,"username":"传智播客","address":"北京金燕龙","sex":"男","birthday":"2018-03-04T12:04:06.000+0000","accounts":[]},
    {"id":46,"username":"老久","address":"北京","sex":"女","birthday":"2018-03-07T17:37:26.000+0000","accounts":[]},
    {"id":48,"username":"小马宝莉","address":"北京修正","sex":"女","birthday":"2018-03-08T11:44:00.000+0000","accounts":[]},
    {"id":51,"username":"李四","address":"广西南宁市","sex":"男","birthday":"2019-07-21T06:29:22.000+0000","accounts":[]},
    {"id":52,"username":"王五","address":"广西桂林市","sex":"男","birthday":"2019-07-20T08:19:50.000+0000","accounts":[]}]
     
    
    
  • 相关阅读:
    SQL Server 查看正在运行的事务信息的 2 种方法。
    SQL Server 查看正在运行的事务信息的 2 种方法。
    js防抖和限流
    js防抖和限流
    CSS cursor 属性
    CSS cursor 属性
    JS-中使用Math.round(x)保留1位小数点
    I/O系列教材 (一)- Java 的File类,以及常用方法
    异常处理系列教材 (五)- Java 自定义异常
    异常处理系列教材 (四)- java Throwable接口
  • 原文地址:https://www.cnblogs.com/hcklqy/p/11666936.html
Copyright © 2020-2023  润新知