解决 mybatis 中相互关联的两种表数据在返回前端时一直循环查询,直到StackOverFlow报错
Posted 水中游鱼
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了解决 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":[]}]
以上是关于解决 mybatis 中相互关联的两种表数据在返回前端时一直循环查询,直到StackOverFlow报错的主要内容,如果未能解决你的问题,请参考以下文章
五 Mybatis一对一关联查询的两种方式(基于resultType&基于resultMap)
关于mybatis中的实体类属性与数据库中的列名不一致的两种解决方法
mybatis高级_数据库中的列和实体类不匹配时的两种解决方法_模糊查询_只能标签
Mybatis一对多查询的两种姿势,你值得拥有(收藏就完事了)