Json序列化,有多对一和多对多关系时出现的问题

Posted 嗯~

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Json序列化,有多对一和多对多关系时出现的问题相关的知识,希望对你有一定的参考价值。

/**  
     * 这是一张  单表中的双向一对多,多对一 关系。自己跟自己一对多多对一
*/  
@Entity
@Table(name="tb_test")
public class CreditsEventBean implements Serializable{
    private static final long serialVersionUID = 1L;
     
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Integer id; //序号
    
    
    /**  
     * 上级分类  
     */ 

    @ManyToOne
    @JoinColumn(name = "pid")  
    private CreditsEventBean pid;    
        
    /**  
     * 下级分类  
     */  
    @OneToMany(mappedBy="pid") 
    private List<CreditsEventBean>  creditsEventBean;
    

 ※ 上面的实体被使用时会出现死循环的问题  如图:

java.lang.IllegalStateException: Cannot call sendError() after the response has been committed
    at org.apache.catalina.connector.ResponseFacade.sendError(ResponseFacade.java:478) ~[tomcat-embed-core-8.0.30.jar:8.0.30]
    at org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver.sendServerError(DefaultHandlerExceptionResolver.java:488) ~[spring-webmvc-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver.handleHttpMessageNotWritable(DefaultHandlerExceptionResolver.java:402) ~[spring-webmvc-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver.doResolveException(DefaultHandlerExceptionResolver.java:146) ~[spring-webmvc-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at org.springframework.web.servlet.handler.AbstractHandlerExceptionResolver.resolveException(AbstractHandlerExceptionResolver.java:137) [spring-webmvc-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at org.springframework.web.servlet.handler.HandlerExceptionResolverComposite.resolveException(HandlerExceptionResolverComposite.java:74) [spring-webmvc-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at org.springframework.web.servlet.DispatcherServlet.processHandlerException(DispatcherServlet.java:1182) [spring-webmvc-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at org.springframework.web.servlet.DispatcherServlet.processDispatchResult(DispatcherServlet.java:1020) [spring-webmvc-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:971) [spring-webmvc-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:893) [spring-webmvc-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:969) [spring-webmvc-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:871) [spring-webmvc-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:648) [tomcat-embed-core-8.0.30.jar:8.0.30]
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:845) [spring-webmvc-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:729) [tomcat-embed-core-8.0.30.jar:8.0.30]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:291) [tomcat-embed-core-8.0.30.jar:8.0.30]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) [tomcat-embed-core-8.0.30.jar:8.0.30]
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) [tomcat-embed-websocket-8.0.30.jar:8.0.30]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239) [tomcat-embed-core-8.0.30.jar:8.0.30]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) [tomcat-embed-core-8.0.30.jar:8.0.30]
    at org.jasig.cas.client.util.AssertionThreadLocalFilter.doFilter(AssertionThreadLocalFilter.java:50) [cas-client-core-3.3.3.jar:3.3.3]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239) [tomcat-embed-core-8.0.30.jar:8.0.30]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) [tomcat-embed-core-8.0.30.jar:8.0.30]
    at org.jasig.cas.client.util.HttpServletRequestWrapperFilter.doFilter(HttpServletRequestWrapperFilter.java:70) [cas-client-core-3.3.3.jar:3.3.3]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239) [tomcat-embed-core-8.0.30.jar:8.0.30]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) [tomcat-embed-core-8.0.30.jar:8.0.30]
    at org.jasig.cas.client.validation.AbstractTicketValidationFilter.doFilter(AbstractTicketValidationFilter.java:238) [cas-client-core-3.3.3.jar:3.3.3]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239) [tomcat-embed-core-8.0.30.jar:8.0.30]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) [tomcat-embed-core-8.0.30.jar:8.0.30]
    at org.jasig.cas.client.authentication.AuthenticationFilter.doFilter(AuthenticationFilter.java:152) [cas-client-core-3.3.3.jar:3.3.3]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239) [tomcat-embed-core-8.0.30.jar:8.0.30]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) [tomcat-embed-core-8.0.30.jar:8.0.30]
    at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99) [spring-web-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239) [tomcat-embed-core-8.0.30.jar:8.0.30]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) [tomcat-embed-core-8.0.30.jar:8.0.30]
    at org.springframework.web.filter.HttpPutFormContentFilter.doFilterInternal(HttpPutFormContentFilter.java:87) [spring-web-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239) [tomcat-embed-core-8.0.30.jar:8.0.30]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) [tomcat-embed-core-8.0.30.jar:8.0.30]
    at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:77) [spring-web-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239) [tomcat-embed-core-8.0.30.jar:8.0.30]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) [tomcat-embed-core-8.0.30.jar:8.0.30]
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:121) [spring-web-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239) [tomcat-embed-core-8.0.30.jar:8.0.30]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) [tomcat-embed-core-8.0.30.jar:8.0.30]
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:212) [tomcat-embed-core-8.0.30.jar:8.0.30]
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106) [tomcat-embed-core-8.0.30.jar:8.0.30]
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502) [tomcat-embed-core-8.0.30.jar:8.0.30]
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:141) [tomcat-embed-core-8.0.30.jar:8.0.30]
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79) [tomcat-embed-core-8.0.30.jar:8.0.30]
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88) [tomcat-embed-core-8.0.30.jar:8.0.30]
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:521) [tomcat-embed-core-8.0.30.jar:8.0.30]
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1096) [tomcat-embed-core-8.0.30.jar:8.0.30]
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:674) [tomcat-embed-core-8.0.30.jar:8.0.30]
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1500) [tomcat-embed-core-8.0.30.jar:8.0.30]
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1456) [tomcat-embed-core-8.0.30.jar:8.0.30]
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [na:1.8.0_181]
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [na:1.8.0_181]
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-8.0.30.jar:8.0.30]
    at java.lang.Thread.run(Thread.java:748) [na:1.8.0_181]

解决方法:

@Entity
@Table(name="tb_test")
public class CreditsEventBean implements Serializable{
    private static final long serialVersionUID = 1L;
     
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Integer id; //序号
    


/**
@JsonBackReference和@JsonManagedReference:这两个标注通常配对使用,通常用在父子关系中。
*/


    /**  
     * 上级分类  
     */ 
    @JsonBackReference //标注的属性在序列化(serialization,即将对象转换为json数据)时,会被忽略(即结果中的json数据不包含该属性的内容)
    @ManyToOne
        @JoinColumn(name = "pid")
        private CreditsEventBean pid;    
        
    /**  
     * 下级分类  
     */  
        @JsonManagedReference//标注的属性则会被序列化。
    @OneToMany(mappedBy="pid") 
    private List<CreditsEventBean>  creditsEventBean;    

 

如果想不忽略 pid字段  (注意:被忽略的字段前端是拿不到值的)则:

@Entity
@Table(name="tb_test")
public class CreditsEventBean implements Serializable{
    private static final long serialVersionUID = 1L;
     
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Integer id; //序号
   


    /**  
     * 上级分类  
     */ 
    @ManyToOne
        @JoinColumn(name = "pid")
        private CreditsEventBean pid;    
        
    /**  
     * 下级分类  
     */  

    @OneToMany(mappedBy="pid") 
    @JsonIgnoreProperties("pid") //指定字段不会被序列化
    private List<CreditsEventBean>  creditsEventBean; 

 

 

 

除此之外还可以:
@JsonIgnore:直接忽略某个属性,以断开无限递归,序列化或反序列化均忽略。当然如果标注在get、set方法中,则可以分开控制,序列化对应的是get方法,反序列化对应的是set方法。

@JsonIgnore跟@JsonBackReference和@JsonManagedReference最大的区别:在父子关系中,当反序列化时,@JsonIgnore不会自动注入被忽略的属性值(父或子)

 

 

后记:在序列化时,@JsonBackReference的作用相当于@JsonIgnore,此时可以没有@JsonManagedReference。但在反序列化(deserialization,即json数据转换为对象)时,如果没有@JsonManagedReference,则不会自动注入@JsonBackReference标注的属性(被忽略的父或子);如果有@JsonManagedReference,则会自动注入自动注入@JsonBackReference标注的属性。 

 

 

 

@Entity
@Table(name="tb_credits_event")
public class CreditsEventBean implements Serializable{
    private static final long serialVersionUID = 1L;
    
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Integer id; //序号
    private String imagePath;//图片路径
    private String title;     //标题
    private String content;  //内容
    private String eventRule;  //活动规则
    private Integer credit;  //积分值    
    private Integer creditStatus;//事件类型  0消费,1获取
    private Integer activityShop;//属于活动的商品   0:常规商品    1:活动商品
    private Integer isShopEvent; //是商品兑换还是活动兑换 0商品兑换  1活动兑换
    private String activityStartCreditsDT;//开始时间
    private String activityEndCreditsDT;//结束时间
    private String userName; //创建者
    private String creteateTime;//创建时间 (活动发布时间)
    private String cutOffTime;//活动报名截止日期
    private String address;//兑换(参与)地址
    private Integer maxPlayers;  //活动限制人数
    private Integer remaining;  //剩余人数
    private Integer sort = 1;//排序 -- 用于内容展示时 过期内容的下沉(默认为1)
    @OneToOne
    @JoinColumn(name="role_id")//与权限表一对一
    private CreditsRoleBean roleBean;//活动有权限设置
    
    
    /**  
     * 上级分类  
     */
//    @JsonBackReference
    @ManyToOne
    @JoinColumn(name = "pid")
    private CreditsEventBean pid;    
        
    /**  
     * 下级分类  
     */  
//    @JsonManagedReference
    @OneToMany(mappedBy="pid")
//    @JsonIgnoreProperties("pid") //指定字段不会被序列化
    private List<CreditsEventBean>  creditsEventBean;//活动跟商品之间关联















































以上是关于Json序列化,有多对一和多对多关系时出现的问题的主要内容,如果未能解决你的问题,请参考以下文章

我们如何在 Keras 中定义一对一、一对多、多对一和多对多的 LSTM 神经网络? [复制]

Mybatis入门

hibernate入门三之关联映射(一对多和多对一)

如何在 DynamoDB 中建模一对一、一对多和多对多关系

Hibernate关联关系配置(一对多一对一和多对多)

thinkphp一对一和多对多关系