我有一个父母(程序)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();
}
答案 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辅助方法。