Java对象序列化所引起的关于循环引用的思考
来源:优易学  2011-1-7 10:36:03   【优易学:中国教育考试门户网】   资料下载   IT书店
 在Java中的模型关系设计中,循环的关系是很常见的,特别是ORM的出现,关系的循环更加有利于维护各自的状态。但就是这种循环的关系,在java对象序列化时,不可避免的会导致循环引用(Cycle Reference)的问题。
  导致CycleReference的情况
  还是举个例子吧(代码说话):一个很典型,很常见的双向引用的对象关系。
  @Entity
  public class Company{
  @Id
  @Column(....)
  private String id;
  @OneToMany(....)
  private Employee employee;
  //setters/getters
  ......
  }
  @Entity
  public class Employee{
  @Id
  @Column(....)
  private String id;
  @ManyToOne
  private Company company;
  //setters/getters
  ......
  }
  另外一种导致这个问题的情况是,多个对象间关系形成一条回路,跟电学有点像。(具体就不举例了,在模型设计时,最好还是避免出现这种情况。)
  导致这种问题的原因
  用jaxb(如果没有特殊解释,本文采用的都是jaxb)序列化Company时,无疑会发生循环引用。
  当序列化引擎解析Company时,它发现这个对象持有一个Employee的引用,转而去骚扰Employee.解析Employee时,发现他又持有Company的引用,又转回Company.如此问题产生。
  引擎它并不知道在遇到循环引用问题时,该怎么处理,它只是忠实得按照固定的算法去执行任务。所以我们得让引擎聪明点,我们得让引擎遇到这种问题有处理机制。
  解决问题
  既然需要引擎更聪明,那就没办法,就得烧香拜佛,希望制造商的产品扩展性足够好,考虑了足够多的情况。
  幸运的是,jaxb提供了有这种扩展。(CycleRecoverable接口)
  行军打仗(例子先行):(将以上的例子改下)
  @Entity
  public class Company implements CycleRecoverable{
  @Id
  @Column(....)
  private String id;
  @OneToMany(....)
  private Employee employee;
  //当遇到循环引用时,用temp替代this,返给jaxb解析。
  public Object onCycleDetected(Context arg0) {
  Company temp = new Company ();
  temp.setId(id);
  return temp;
  }
  //setters/getters
  ......
  }
  @Entity
  public class Employee implements CycleRecoverable{
  @Id
  @Column(....)
  private String id;
  @ManyToOne
  private Company company;
  public Object onCycleDetected(Context arg0) {
  Employee temp = new Employee();
  temp.setId(id);
  return temp;
  }
  //setters/getters
  ......
  }
  注意到onCycleDetected方法就是一个回调方法,当遇到循环引用时,jaxb引擎会调用这个方法,用return对象来替换this.所以在这个过程中,就可以将引起循环引用问题的关系断开,返回给jaxb.
  当然Company和Employee对象没必要全部实现CycleRecoverable接口,但是拿到现实的模型图中去,谁也保证不了他们不跟别的对象有循环的关系存在。因此还是建议大家把模型都实现这个接口,也好一劳永逸。

责任编辑:小草

文章搜索:
 相关文章
热点资讯
资讯快报
热门课程培训