Hello, With two entities mapped as:
@Entity
@Table(name="table_a")
public class A {
@OneToMany(fetch = FetchType.LAZY, cascade=CascadeType.ALL, mappedBy="a", orphanRemoval=true)
@OrderColumn(name="rank")
private List<B> listB = new ArrayList<>();
public void addB(B b) {
listB.add(b);
}
}
@Entity
@Table(name="table_b")
public class B {
@ManyToOne(optional = false, fetch = FetchType.LAZY)
@JoinColumn(name="blob_id", nullable = false, insertable = true, updatable = false)
private A a;
}
I have an entity of type A, with no values in the list. When some code opens this entity, and directly calls “addB”, the resulting sql statements do insert a new row in table_b, but the rank value happens to be 1 if there was no direct access to the lazy listB`. If I add listB.size() before add in the addB call, then the index is valid. When I do the “add on a not yet loaded lazy list”, then the next read results in the listB containing two elements: null, then my B instance, because of the wrong rank=1 value that has been inserted. Looking at the sql traces, in the case I forget to fetch the lazy list before add, I see the calls:
When there are elements in the list, the formula max(rank)+1 results in the correct value for the added element being chosen. But when there is no element at all, the result appear to be 1 when the correct value would be 0. It looks like the formula from https://github.com/hibernate/hibernate-orm/blob/7d30b57f15617f679a20aa1389c9385433e45b2c/hibernate-core/src/main/java/org/hibernate/persister/collection/AbstractCollectionPersister.java#L1268 is too simple, and should take into account the case when there are no elements found. |