循环序列化与Hibernate的多对多关系

时间:2010-02-08 05:07:28

标签: java hibernate orm jpa

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

问题在于它序列化一个程序,它还序列化了程序的订阅者,这涉及序列化他们的程序,这涉及序列化他们的订阅者,直到它序列化每个程序&数据库中的订阅者。

ERD看起来像:程序< - >订户

这意味着返回的17KB小数据块(json)的回报率为6.9MB。这反过来又耗尽了序列化数据然后将其返回的时间。

为什么我的父母回来的孩子会让父母回来的孩子?如何阻止这一点,以便我只获得每个程序的订阅者?我假设我的注释做错了,也许吧?我想保持多对多的关系,但没有这种深度嵌套的数据检索。

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

Program.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; }

Subscriber.java

@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();
}

5 个答案:

答案 0 :(得分:3)

您没有提到您用于JSON序列化的框架,因此我将假设JAXB。无论如何,我们的想法是以某种方式使Subscriber.getPrograms(..)瞬态,因此它不是序列化的。 Hibernate负责处理这些'循环',但其他人则没有。所以:

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

如果您使用其他框架,则它可能具有不同的注释/配置以指定瞬态字段。与transient关键字一样。

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

答案 1 :(得分:1)

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

答案 2 :(得分:1)

答案 3 :(得分:0)

来自龙目岛图书馆。或覆盖等于和哈希码。在内部哈希码中仅使用唯一字段(例如id)。

@EqualsAndHashCode(callSuper = false, of = {"id"})

答案 4 :(得分:-1)

Bozho和ponkin都在正确的轨道上。我需要停止将数据序列化,但最大的问题是我无法更改pojo - &gt; toJSON类/方法,其中进行序列化。我还担心在toJSON()方法上投入时间,因为我在序列化时遇到了这样的性能损失,我想要在我获得数据之前而不是之后发生修复。

同样由于我列出的多对多双向设计的性质,我总是会遇到这个循环程序/订阅者/程序/ ...问题。

解决方案:(现在至少)我已经删除了Subscriber.getProgram()方法,并在ProgramDAO上创建了一个finder方法,该方法返回Subscriber中的Programs。

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辅助方法。