1. 程式人生 > >Json序列化,有多對一和多對多關係時出現的問題

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;//活動跟商品之間關聯