Reputation: 1489
Can somebody explain the following strange behaviour I encountered? I am trying to persist some new child objects and simultaneously add them to to the parent collection. At the end there are twice as many elements in parent collection as I expected. Let me show the example:
@Entity
public class A {
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Id
private Integer id;
@OneToMany(mappedBy = "a")
private List<B> bs = new ArrayList<>();
public Integer getId() { return id; }
public void setId(Integer id) { this.id = id; }
public List<B> getBs() { return bs; }
public void setBs(List<B> bs) { this.bs = bs; }
}
@Entity
public class B {
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Id
private Integer id;
@ManyToOne
private A a;
public Integer getId() { return id; }
public void setId(Integer id) { this.id = id; }
public A getA() { return a; }
public void setA(A a) { this.a = a; }
}
Test case:
@Test
public void test() throws Exception {
entityManager.getTransaction().begin();
A a = new A();
entityManager.persist(a);
entityManager.flush();
entityManager.clear();
a = entityManager.find(A.class, a.getId());
for (int i = 0; i < 3; i++) {
B b = new B();
b.setA(a);
entityManager.persist(b);
a.getBs().add(b);
}
assertEquals(3, a.getBs().size());
entityManager.getTransaction().commit();
}
Result:
java.lang.AssertionError:
Expected :3
Actual :6
I don't ask how to modify given code to achieve expected result. I want to understand why given code behaves like this.
Thanks to @riskop answer and my further investigation we can summarize:
Upvotes: 1
Views: 125
Reputation: 1787
Unfortunately I can't tell you exactly how this happening
But I would say that this is a Hibernate bug. It should return 3.
I checked this with Hibernate 5.0.3.Final and experienced the same problem. Then I checked the exact same code with DataNucleus 4.1.9 and that works as expected (no duplicate size of the collection).
However, even with Hibernate the problem goes away if you do any of the following:
Upvotes: 1
Reputation: 183
I'm not terribly familiar with either Hibernate or Spring, but should
entityManager.flush();
entityManager.clear();
be called after
entityManager.persist(b);
(possibly in addition to where you already have it)
Upvotes: 0