- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
这个场景使用一个简单的 oneToMany 关系,在两个方向上都保持级联。
许多:
@javax.persistence.Entity(name="Many")
public class Many {
@javax.persistence.ManyToOne(cascade = CascadeType.PERSIST)
protected One one;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long primaryKey;
public void setM(One one) {
this.one = one;
// comment out this line and performance becomes stable
this.one.getMany().add(this);
}
// other setters, getters, etc...
}
一:
@javax.persistence.Entity(name="One")
public class One {
@javax.persistence.OneToMany(mappedBy="m", cascade = CascadeType.PERSIST)
protected java.util.Set<Many> many = com.google.common.collect.Sets.newHashSet();
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long primaryKey;
private String name;
// setters, getters, etc...
}
测试:
public static void main(String[] args) {
while(true) {
EntityManagerFactory emf = Persistence.createEntityManagerFactory("test-pu");
EntityManager em = emf.createEntityManager();
for (int i = 0; i < 100; i++) {
sw.reset();
sw.start();
persistMVs(emf, em);
System.err.println("Elapsed: " + sw.elapsed(TimeUnit.MILLISECONDS) + " ms");
}
em.close();
emf.close();
}
}
private static void persistMVs(EntityManagerFactory emf, EntityManager em) {
em.getTransaction().begin();
One one = getOrCreateOne(em);
for (int i = 0; i < 200; i++) {
Many many = new Many();
many.setM(one);
em.persist(many);
}
em.getTransaction().commit();
}
该测试是一个无限循环,它尝试插入 20000 个与单个 One
实体关联的 Many
实体。每个循环都从创建一个新的 EntityManagerFactory
开始,以显示不断增加的数据库对性能的负面影响。
预期的行为是,实体的插入时间不会急剧增加,但是在每个 WHILE CYCLE 之后都会有一个数量级的增加。
注意事项:
em.persist(many);
(我测过的)。gradle 开始
。为什么在这种情况下数据库的初始大小很重要?我应该将此行为视为错误吗?
最佳答案
只是为了扩展 Predrag 的回答——遍历 1:M 关系不仅有引入实体的成本,而且任何扩展对象图,但这些实体仍然在持久单元内管理。因为您的测试为重复事务重复使用相同的 EntityManager,所以托管实体的缓存会随着每次迭代而持续增长。每次上下文与数据库同步时,都必须遍历并检查托管实体的缓存是否有更改 - 这发生在刷新、事务提交甚至查询时。
如果您必须引入大型对象图,可以采取的措施是为每个事务边界释放和获取新的 EntityManager,或者偶尔刷新并清除 EntityManager。任一选项都允许它释放一些托管实体,因此它不需要在每次提交时检查所有实体是否有更改。
编辑>您的“Many”类已覆盖 hashCode 方法,并使用其引用的“One”的哈希码及其主键来构建其哈希码。这会导致您在循环中坚持的每个“许多”都具有相同的哈希码,因为 GenerationType.IDENTITY 只能在插入语句发生时分配序列 - 这发生在同步(刷新/提交)期间。此方法可能会导致缓存查找(由于级联持久调用而导致提供程序在每个持久调用上遍历不断增长的对象模型时发生)花费越来越长的时间。
关于hibernate - JPA 坚持变得越来越慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35700404/
我是一名优秀的程序员,十分优秀!