Mybatis懒加载时,springMVC返回JSON异常 Could not write JSON: No serializer found for class
错误信息如下:
错误信息: com.fasterxml.jackson.databind.JsonMappingException:
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_EMPTYBEANS) ) (through reference
chain: java.util.HashMap[“XXX”]->java.util.ArrayList[0]->com.moguichun.model.XXX$$_jvst552_0[“handler”])
错误原因
在mybatis集成springmvc时,假如mybatis采用了懒加载,而springmvc中利用@ResponseBody注解返回实体类的JSON时会抛异常
错误分析
分析的代码如下:
首先是controller中返回的是responsebody:
CategoryController.java
//将查询的结果放入map传给前端,以json的格式
@ResponseBody
@RequestMapping(value="/categoryList", method=RequestMethod.GET)
public Map<String,Object> categoryList(){
Map<String,Object> map = new HashMap<>();
List<MainCategory> categoryList = this.categoryService.categoryList();
if(null!=categoryList && categoryList.size() > 0) {//控制层做简单判断,并将信息放入map中
map.put("code", 1001);
map.put("message", "查询成功");
map.put("categoryList", categoryList);
}else {
map.put("code", 1002);
map.put("message", "查询失败");
}
return map;
}
service中的代码:
CategoryServiceImpl.java
//返回目录list
@Override
public List<MainCategory> categoryList() {
List<MainCategory> categoryList = this.categoryDao.selectAllMainCategory();
return categoryList;
}
调用的mapper.xml中使用了懒加载:
mybatis-config.xml
<configuration>
<settings>
<!-- 开启延迟加载lazyLoadingEnabled\aggressiveLazyLoading -->
<setting name="lazyLoadingEnabled" value="true"/>
<setting name="aggressiveLazyLoading" value="false"/>
</settings>
</configuration>
ICategoryDao .java
@Mapper
public interface ICategoryDao {
/**
* 查询一级目录,包含二级目录
* @return
*/
public List<MainCategory> selectAllMainCategory();
}
ICategoryDao .xml
<mapper namespace="com.zym.dao.ICategoryDao">
<resultMap type="com.zym.entities.MainCategory" id="myCategory">
<id column="main_category_id" property="mainCategoryId"/>
<collection property="subCategoryList" column="main_category_id" select="com.zym.dao.ICategoryDao.selectSubCategoryByMainCategoryId" ></collection>
</resultMap>
<!-- 查询一级目录 List<MainCategory> selectAllMainCategory() -->
<select id="selectAllMainCategory" resultMap="myCategory">
SELECT `main_category_id`,`category_name` FROM `main_category`
</select>
<!-- 查询二级目录 List<MainCategory> selectSubCategoryByMainCategoryId(Integer mainCategoryId) -->
<select id="selectSubCategoryByMainCategoryId" resultType="com.zym.entities.SubCategory">
SELECT `sub_category_id`,`category_name` FROM `sub_category` WHERE `main_category_id` = #{mainCategoryId}
</select>
</mapper>
这个时候测试就会上面的异常.
经过调试后发现,MyBatis执行了DAO层的方法后,返回的实体类MainCategory被做了代理,如下:
可以看到,被代理后的MainCategory类多了一个 handler的属性 ,之后Jackson在对该代理类做序列化时,由于找不到对应的getter,抛出来异常
解决方法
1、在被代理的MainCategory类上加上 @JsonIgnoreProperties(value = “handler”) 注解,让Jackson序列化时忽略handler属性,这样Jackson序列化时,就不会去调用handler属性的get/set方法
@JsonIgnoreProperties(value = { "handler" })
public class MainCategory implements Serializable{
private Integer mainCategoryId;
private String categoryName;
private List<SubCategory> subCategoryList;//二级目录集合
2、关闭该查询的懒加载 fetchType=“eager”
<resultMap type="com.zym.entities.MainCategory" id="myCategory">
<id column="main_category_id" property="mainCategoryId"/>
<collection property="subCategoryList" column="main_category_id" fetchType="eager" select="com.zym.dao.ICategoryDao.selectSubCategoryByMainCategoryId" ></collection>
</resultMap>
3、配置json转换器属性SerializationFeature.FAIL_ON_EMPTY_BEANS为false