浅析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>