Hibernate懒加载导致json数据对象传输异常的问题---(非常重要)

1. 异常:

[console_demo][WARN] [2016-12-15 19:49:35] org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver.handleHttpMessageNotWritable(407) | Failed to write HTTP message: org.springframework.http.converter.HttpMessageNotWritableException: Could not write content: No serializer found for class org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) (through reference chain: java.util.HashMap["ckRequirePartLists"]->java.util.ArrayList[0]->com.dyoon.cmms.pojo.CkRequirePartList["ckPurchaseBill"]->com.dyoon.cmms.pojo.CkPurchaseBill["applyOperator"]->com.dyoon.cmms.pojo.UserOperator_$$_jvsta2a_12["sysRole"]->com.dyoon.cmms.pojo.SysRole_$$_jvsta2a_8["userModifyLog"]->com.dyoon.cmms.pojo.UserModifyLog_$$_jvsta2a_6["handler"]); nested exception is com.fasterxml.jackson.databind.JsonMappingException: No serializer found for class org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) (through reference chain: java.util.HashMap["ckRequirePartLists"]->java.util.ArrayList[0]->com.dyoon.cmms.pojo.CkRequirePartList["ckPurchaseBill"]->com.dyoon.cmms.pojo.CkPurchaseBill["applyOperator"]->com.dyoon.cmms.pojo.UserOperator_$$_jvsta2a_12["sysRole"]->com.dyoon.cmms.pojo.SysRole_$$_jvsta2a_8["userModifyLog"]->com.dyoon.cmms.pojo.UserModifyLog_$$_jvsta2a_6["handler"])

2. 原因:

使用注解@ResponseBody返回由Hibernate DAO直接获得的pojo对象内存在Lazy关联对象,执行Jason转换时,会从数据库加载该对象,而此时session已关闭,导致加载失败,进而导致Jason转换失败。


3  解决:

方法一:在不影响数据完整性的情况下,使用set方法手动置空pojo类的Lazy关联对象。(这样如果关联的对象比较多,可能漏的。)

方法二:使用@JsonIgnore注释掉pojo类的Lazy关联对象。(这种如果在其他的地方需要用关联的对象转json,这样就会导致失效。)

方法三:自定义类,二次封装所需的pojo对象的属性。


4. 事例:以下对第三种方法做展示

jsp页面:

	function showPartDetails(purchBillId){
	   		
	   $.ajax({
		type:"post",
		url:"${rootPath }/depot/purchase/getPartByPurchBillId?purchBillId="+purchBillId,	
		success : function(data){
 			alert(data.requirePartListBeans[0].partName);
				}
			});   		   		
	   	}
通过ajax发送请求到controller,服务器处理结果,将结果以json的格式发送给前端。

常规下的controller如下:

        @RequestMapping(value = "/getPartByPurchBillId")
	@ResponseBody
	public Map<String,Object> getPartByPurchBillId(@RequestParam(value="purchBillId") Integer purchBillId) throws JsonProcessingException {
		Map<String, Object> map = new HashMap<>();
		List<CkRequirePartList> ckRequirePartLists = purchaseService.getPartByPurchBillId(purchBillId);
		map.put("requirePartListBeans", ckRequirePartLists);
         return map;
	}
但是由于hibernate懒加载的问题,requirePartListBeans不能正常的转换为json,这时候将前端要获取的属性数据封装成一个类,以下为假如前端要获取的3条数据:

public class RequirePartListBean {
	
	private String partNumber;
	private String partName;
	private BigDecimal partQuantity;

	public String getPartNumber() {
		return partNumber;
	}

	public void setPartNumber(String partNumber) {
		this.partNumber = partNumber;
	}

	public String getPartName() {
		return partName;
	}

	public void setPartName(String partName) {
		this.partName = partName;
	}

	public BigDecimal getPartQuantity() {
		return partQuantity;
	}
	
	public void setPartQuantity(BigDecimal partQuantity) {
		this.partQuantity = partQuantity;
	}
}
更改后的controller为:

        @RequestMapping(value = "/getPartByPurchBillId")
	@ResponseBody
	public Map<String,Object> getPartByPurchBillId(@RequestParam(value="purchBillId") Integer purchBillId) throws JsonProcessingException {
		Map<String, Object> map = new HashMap<>();
		List<CkRequirePartList> ckRequirePartLists = purchaseService.getPartByPurchBillId(purchBillId);
		RequirePartListBean r = null;
		List<RequirePartListBean> requirePartListBeans = new ArrayList<>();
		for (CkRequirePartList ckRequirePartList : ckRequirePartLists) {
			r = new RequirePartListBean();
			r.setPartName(ckRequirePartList.getModPartCatalog().getPartName());
			r.setPartNumber(ckRequirePartList.getModPartCatalog().getPartNumber());
			r.setPartQuantity(ckRequirePartList.getPartQuantity());
			requirePartListBeans.add(r);
		}		
		map.put("requirePartListBeans", requirePartListBeans);
		return map;
	}
前端ajax通过success响应数据,
success : function(data){
 	alert(data.requirePartListBeans[0].partName);
}

至此,问题得到解决。还有问题的可以留言。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值