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

落花浮王杯 提交于 2019-12-01 07:12:12

原代码设计:

一个用户有多个账户,是一对多的关系,用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:
@Repositorypublic 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":[]}]
 

 


易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!