浅析mybatis懒加载导致无法序列化的问题、Json序列化对象时错误Could not write JSON: No serializer found for class

一、问题背景

  在使用 MyBtais resultMap 一对多时,查数据报错:

Unable to serialize claims object to json: Unable to serialize object: No serializer found for class org.apache.ibatis.executor.loader.javassist.JavassistProxyFactory$EnhancedResultObjectProxyImpl and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) (through reference chain: io.jsonwebtoken.impl.DefaultClaims[\"userInfo\"]->top.jybill.domain.MyUser_$$_jvst2e5_0[\"handler\"])

  起初不知道为啥,查资料了解到,总而言之:Bug原因是 - 因为mybatis的懒加载原因

<resultMap id="order" type="order">
        <id property="id" column="id" />
        <result property="orderNum" column="orderNum" />
        <result property="orderTime" column="orderTime" />
        <result property="orderStatus" column="orderStatus" />
        <result property="peopleCount" column="peopleCount" />
        <result property="payType" column="payType" />
        <result property="orderDesc" column="orderDesc" />
        <association column="productId" property="product"
                     select="top.jybill.dao.IProductDao.findProductById"
                     fetchType="eager" />
</resultMap>

  起初我没有fetchType属性,默认是lazy懒加载, 修改成eager后成功序列化

  因为我是一对一的,一般情况不需要懒加载,如果是一对多必须懒加载的情况则需给实体类加上 @JsonIgnoreProperties(value = "handler") 注解

二、解决方案

1、在实体类上加注解:@JsonIgnoreProperties(value = {"handler"})

  在所有相关的类前加上@JsonIgnoreProperties, 作用是json序列化时忽略bean中的一些属性序列化和反序列化时抛出的异常

2、或者在 <collection> 中加入:fetchType="eager"

3、关闭/不启用mybatis懒加载(mybatis默认关闭)

三、问题分析

  在mybatis集成springmvc,假如mybatis采用了懒加载,而在控制器中把返回的数据序列化成Json格式字符串,则会抛出异常:

There was an unexpected error (type=Internal Server Error, status=500).
Could not write JSON: No serializer found for class org.apache.ibatis.reflection.factory.DefaultObjectFactory and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS)

  原因是MyBatis代理的实体对象被代理后的类多了一个handler的属性,之后Jackson在对该代理类做序列化时,由于找不到对应的 getter,异常就抛出来了。

  解决方法:

1、在被代理的类上加上 @JsonIgnoreProperties(value = "handler") 注解,让Jackson序列化时忽略handler属性,如:

@JsonIgnoreProperties(value= {"handler"})
public class Student implements Serializable {}

2、在MyBatis的映射文件中把懒加载改成即时加载 fetchType="eager" ,默认值是 "lazy":

<resultMap type="Student" id="studentMap">
   <association property="grade" column="gradeId"
     select="com.bdqn.dao.GradeDao.findById" fetchType="eager"></association>
</resultMap>

 

posted @ 2020-06-15 23:51  古兰精  阅读(1693)  评论(0编辑  收藏  举报