gpt4 book ai didi

java - 双向变得比单向慢得多

转载 作者:行者123 更新时间:2023-12-02 12:32:26 25 4
gpt4 key购买 nike

关闭。这个问题是not reproducible or was caused by typos .它目前不接受答案。












想改进这个问题?将问题更新为 on-topic对于堆栈溢出。

4年前关闭。




Improve this question




在 Java/Hibernate 应用程序中,我有两个类 CatKitten如下图所示的双向关系:

public class Cat {
...
@OneToMany(mappedBy="cat", fetch = FetchType.LAZY)
@OnDelete(action = OnDeleteAction.CASCADE)
@LazyCollection(LazyCollectionOption.EXTRA)
@Getter
@Setter
private List<Kitten> kittens = new LinkedList();
public void addKitten(Kitten k) {
kittens.add(k);
}
...
}

public class Kitten {
...
@ManyToOne(fetch=FetchType.LAZY)
@Getter
@Setter
private Cat cat;
...
}

在一个巨大的 for 循环中 20000 Kitten被添加到不同的 Cat之前创建的实体。 for循环中的重要代码如下所示:
....
Kitten k = new Kitten();
k.setAttribut("foo");
k.setCat(currentCat); // (a) line
currentCat.addKitten(k); // (b) line
daoFactory.getKittenDao().save(k);
...

代码正在运行,但不知何故,性能非常慢。在以前的迭代(单向)中,应用程序要快得多。由于最终版本应该在 1000000 Kitten 上工作必须有改进的方法。如果我对上述代码的时间进行基准测试,大约需要 40 秒。如果我通过删除线 (a) 或 (b) 来模拟单向,则在这两种情况下都需要 10 秒(但如果我访问对象,则会稍后崩溃)。

所以我的问题是:
我错过了什么,或者在 Hibernate 中双向关系的内部维护非常慢?由于模拟单向要快得多,我预计双向的运行时间约为 15 秒。

更新:

保存实体的代码位于 SAX-Parser DefaultHandler 实现中。因此,在解析 XML 结构时,首先要使用 Cat保存在 startElement() Kitten将保存在另一个 startElement()称呼。
关于@Bartun 的建议/问题:我研究了批处理。问题是,通过使用 DAO 和 startElement()函数,很难说,什么时候准确地保存了 50 个实体来刷新 session 。不过,柜台可以解决问题。但是,它并没有通过建立双向来解释性能影响。
作为事务管理 Spring @Transactional用于开始 XML 解析的函数。

最佳答案

我已将处理时间减少到我可以接受的值。它并没有真正解决我的问题,但大大减少了时间。如果其他人有同样的问题,这里是当前代码和简短的解释。

public class Cat {
...
@OneToMany(mappedBy="cat", fetch = FetchType.LAZY)
@OnDelete(action = OnDeleteAction.CASCADE)
@LazyCollection(LazyCollectionOption.EXTRA)
@Getter
@Setter
private Set<Kitten> kittens = new HashSet();
public void addKitten(Kitten k) {
k.setCat(this);
if (Hibernate.isInitialized(kittens)) kittens.add(k); //line X
}
...
}

public class Kitten {
...
@ManyToOne(fetch=FetchType.LAZY)
@OnDelete(action = OnDeleteAction.CASCADE)
@Getter
@Setter
private Cat cat;
...
}
  • 最重要的是line X .在原始代码中,每次添加一只小猫时,都会从数据库中加载整个小猫列表。正如我发现的 here ,如果列表尚未初始化,则不能添加小猫。我知道,这必须小心完成,因为在首次初始化列表之前,必须将每只小猫保存在数据库中。否则一切都会不同步。
  • 在上面的代码中没有说明,我更改了 kitten persistence 的结构以启用批量插入(Thx Bartun 链接)。现在,所有小猫都在解析过程结束时使用批处理保存,而不是单独保存每只小猫。
  • 还有一个小的改进是对 List 的更改。到 Set启用多个 fetch joins稍后在代码中。
  • 关于java - 双向变得比单向慢得多,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45242694/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com