-
Type:
Bug
-
Resolution: Unresolved
-
Priority:
Unknown
-
None
-
Affects Version/s: None
-
Component/s: Mutation
-
None
-
None
-
None
-
None
-
None
-
None
-
None
-
None
Summary
Removing every element from a unidirectional @OneToMany makes Hibernate ORM emit a mutation that
nulls the foreign key of every row at once rather than row by row. That mutation carries no
optimistic lock bindings, and AbstractMqlTranslator.createKeyFilter iterates
AbstractRestrictedTableMutation.getOptimisticLockBindings() without checking for null.
Reproducer
@Entity @Table(name = "owners") static class Owner { @Id int id; @OneToMany(cascade = CascadeType.PERSIST) @JoinColumn(name = "owner_id") List<Item> items; } @Entity @Table(name = "items") static class Item { @Id int id; }
Persist an Owner holding two {{Item}}s, then in a later transaction load the owner and set
owner.items to null.
java.lang.NullPointerException: Cannot invoke "java.util.List.iterator()" because the return value of "org.hibernate.sql.model.ast.AbstractRestrictedTableMutation.getOptimisticLockBindings()" is null at com.mongodb.hibernate.internal.translate.AbstractMqlTranslator.createKeyFilter(AbstractMqlTranslator.java:475) at com.mongodb.hibernate.internal.translate.AbstractMqlTranslator.visitStandardTableUpdate(AbstractMqlTranslator.java:456) at org.hibernate.sql.model.internal.TableUpdateStandard.accept(TableUpdateStandard.java:118)
Proposed fix
Treat an absent optimistic lock binding list as empty. The key restriction alone is what the mutation
calls for in this case.
Acceptance
Dereferencing the collection completes, and the foreign key of every affected document is cleared.