zoukankan      html  css  js  c++  java
  • 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页面:

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

    常规下的controller如下:

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

    1. public class RequirePartListBean {
    2. private String partNumber;
    3. private String partName;
    4. private BigDecimal partQuantity;
    5. public String getPartNumber() {
    6. return partNumber;
    7. }
    8. public void setPartNumber(String partNumber) {
    9. this.partNumber = partNumber;
    10. }
    11. public String getPartName() {
    12. return partName;
    13. }
    14. public void setPartName(String partName) {
    15. this.partName = partName;
    16. }
    17. public BigDecimal getPartQuantity() {
    18. return partQuantity;
    19. }
    20. public void setPartQuantity(BigDecimal partQuantity) {
    21. this.partQuantity = partQuantity;
    22. }
    23. }
    更改后的controller为:

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

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

    原文地址:https://blog.csdn.net/baidu_28283827/article/details/53675121
  • 相关阅读:
    Android跨进程通信AIDL服务*
    Android跨进程通信广播(Broadcast)*
    Android跨进程通信Content Provider*
    Android跨进程通信访问其他应用程序的Activity*
    Android RecyclerView实现加载多种条目类型*
    Android ListView多布局*
    Android屏幕横竖屏切换和生命周期管理的详细总结*
    Android中的asserts和res/raw资源目录*
    Android系统服务 —— WMS与AMS*
    Android中为什么主线程不会因为Looper.loop()方法造成阻塞
  • 原文地址:https://www.cnblogs.com/jpfss/p/11102963.html
Copyright © 2011-2022 走看看