代码之家  ›  专栏  ›  技术社区  ›  Ben Clark-Robinson

与休眠有多对多关系的循环序列化

  •  1
  • Ben Clark-Robinson  · 技术社区  · 15 年前

    我有一个父母(程序)pojo与他们的孩子(订户)有多对多的关系。

    问题是,当它序列化一个程序时,它还会序列化程序的订户,这涉及到序列化他们的程序,这涉及到序列化他们的订户,直到它序列化数据库中的每个程序和订户为止。

    ERD看起来像:程序订阅服务器

    这意味着返回的17KB数据块(JSON)变成了6.9MB的返回。因此,反过来会耗尽时间来序列化数据,然后返回它。

    为什么我的父母会把孩子送回父母会把孩子送回?我怎样才能停止这一切,这样我就只能得到每个节目的订户?我假设我的注释有问题,也许吧?我想保持一种多对多的关系,但是没有这种深度嵌套的数据检索。

    (注意:我之前尝试过添加尽可能多的懒惰注释,只是为了看看这是否有帮助。没有。也许我也做错事了?)

    程序,Java

    @Entity
    @Table(name="programs")
    public class Program extends Core implements Serializable, Cloneable {
       ...
       @ManyToMany()
       @JoinTable(name="program_subscribers",
             joinColumns={@JoinColumn(name="program_uid")},
             inverseJoinColumns={@JoinColumn(name="subscriber_uid")})
       public Set<Subscriber> getSubscribers() { return subscribers; }
       public void setSubscribers(Set<Subscriber> subscribers) { this.subscribers = subscribers; }
    

    订阅服务器

    @Entity
    @Table(name="subscribers")
    public class Subscriber extends Core implements Serializable {
       ...
       @ManyToMany(mappedBy="subscribers")
       public Set<Program> getPrograms() { return programs; }
       public void setPrograms(Set<Program> programs) { this.programs = programs; 
    

    }

    实施

    public Collection<Program> list() {
      return new Programs.findAll();
    }
    
    4 回复  |  直到 14 年前
        1
  •  3
  •   Bozho    14 年前

    您没有提到用于JSON序列化的框架,所以我假设使用JAXB。总之,我们的想法是 Subscriber.getPrograms(..) 在某种程度上是暂时的,所以不会序列化。Hibernate负责这些“循环”,但其他人不负责。因此:

    @XmlTransient
    @ManyToMany(..)
    public Set<Program> getPrograms()...
    

    如果您使用另一个框架,它可能有不同的注释/配置来指定临时字段。像 transient 关键字。

    另一种方法是自定义映射器以手动处理循环,但这很乏味。

        2
  •  1
  •   ponkin    15 年前

    1)“您的”序列化如何工作。我的意思是它是JAXB还是自定义序列化或smth-else。 2)几乎所有框架都允许您设置序列化的深度。我的意思是你可以把深度设为2。 3)我建议您不要用子对象序列化对象,将它们(childre)标记为瞬态,并单独序列化。

        4
  •  -1
  •   Ben Clark-Robinson    14 年前

    博佐和庞金都在正确的轨道上。我需要停止将数据序列化,但最大的问题是我无法更改进行序列化的pojo->tojson类/方法。我还担心在tojson()方法上花费时间,考虑到我在序列化的时候受到了这样的性能冲击,我希望在获得数据之前而不是之后进行修复。

    另外,由于我列出的多对多双向设计的性质,我总是会有这个循环程序/订阅者/程序。问题。

    解决方法:(至少目前)我已经删除了subscriber.getProgram()方法,并在程序dao上创建了一个finder方法,该方法按订户返回程序。

    public List<Program> findBySubscriber(Subscriber subscriber) {
      String hql = "select p " +
         "from Program p " +
         " join p.subscribers s " +
         "where s = :sub"
         ;    
    
      Query q = getSession().createQuery(hql);
      q.setEntity("sub", subscriber);
    
      List<Program> l = q.list();
      return l;
    }
    

    对于任何CRUD工作,我想我只需要循环访问programs.getsubscribers,或者编写更多的hql helper方法。