After updating to hibernate >= 7.1.9, I get the following error:
Unable to locate parameter
CHILD.PARENT_IDfor RESTRICT - UPDATE : org.hibernate.bugs.ChildEntityA
UnknownParameterException(CHILD.PARENT_IDfor RESTRICT - UPDATE : o.h.b.ChildEntityA)
at org.hibernate.engine.jdbc.mutation.internal.JdbcValueBindingsImpl.bindValue(JdbcValueBindingsImpl.java:59)
at org.hibernate.persister.entity.mutation.AbstractMutationCoordinator.lambda$breakDownKeyJdbcValues$0(AbstractMutationCoordinator.java:212)
at org.hibernate.persister.entity.mutation.EntityTableMapping$AbstractKeyMapping.lambda$breakDownKeyJdbcValues$0(EntityTableMapping.java:312)
at org.hibernate.metamodel.mapping.internal.BasicAttributeMapping.forEachDisassembledJdbcValue(BasicAttributeMapping.java:494)
at org.hibernate.metamodel.mapping.Bindable.forEachJdbcValue(Bindable.java:173)
at org.hibernate.metamodel.internal.AbstractCompositeIdentifierMapping.forEachJdbcValue(AbstractCompositeIdentifierMapping.java:210)
at org.hibernate.metamodel.mapping.Bindable.forEachJdbcValue(Bindable.java:157)
at org.hibernate.persister.entity.mutation.EntityTableMapping$AbstractKeyMapping.breakDownKeyJdbcValues(EntityTableMapping.java:308)
at org.hibernate.persister.entity.mutation.AbstractMutationCoordinator.breakDownKeyJdbcValues(AbstractMutationCoordinator.java:209)
at org.hibernate.persister.entity.mutation.UpdateCoordinatorStandard.decomposeForUpdate(UpdateCoordinatorStandard.java:855)
at org.hibernate.persister.entity.mutation.UpdateCoordinatorStandard.doStaticUpdate(UpdateCoordinatorStandard.java:791)
at org.hibernate.persister.entity.mutation.UpdateCoordinatorStandard.performUpdate(UpdateCoordinatorStandard.java:322)
at org.hibernate.persister.entity.mutation.UpdateCoordinatorStandard.update(UpdateCoordinatorStandard.java:240)
at org.hibernate.action.internal.EntityUpdateAction.execute(EntityUpdateAction.java:161)
at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:634)
at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:505)
at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:381)
at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:40)
at org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:138)
at org.hibernate.internal.SessionImpl.fireFlush(SessionImpl.java:1453)
at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:484)
at org.hibernate.internal.SessionImpl.flushBeforeTransactionCompletion(SessionImpl.java:2080)
at org.hibernate.internal.SessionImpl.beforeTransactionCompletion(SessionImpl.java:2002)
at org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl.beforeTransactionCompletion(JdbcCoordinatorImpl.java:426)
at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.beforeCompletionCallback(JdbcResourceLocalTransactionCoordinatorImpl.java:166)
at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl$TransactionDriverControlImpl.commitNoRollbackOnly(JdbcResourceLocalTransactionCoordinatorImpl.java:251)
at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl$TransactionDriverControlImpl.commit(JdbcResourceLocalTransactionCoordinatorImpl.java:241)
at org.hibernate.engine.transaction.internal.TransactionImpl.commit(TransactionImpl.java:89)
at org.hibernate.testing.orm.transaction.TransactionUtil.wrapInTransaction(TransactionUtil.java:77)
at org.hibernate.testing.orm.transaction.TransactionUtil.inTransaction(TransactionUtil.java:41)
at org.hibernate.testing.orm.junit.SessionFactoryExtension$SessionFactoryScopeImpl.inTransaction(SessionFactoryExtension.java:373)
at org.hibernate.testing.orm.junit.SessionFactoryExtension$SessionFactoryScopeImpl.inTransaction(SessionFactoryExtension.java:350)
at org.hibernate.bugs.ORMUnitTestCase.hhh123Test(ORMUnitTestCase.java:56)
at java.base/java.lang.reflect.Method.invoke(Method.java:565)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1604)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1604)
One weird thing is that in my Quarkus application, the bug happens ~50% of the time: When you start the application, the exception will either always be thrown or never; it’s decided at startup and stays consistent. However, in the minimal reproducible example below, the exception is always thrown.
@DomainModel(
annotatedClasses = {
ParentEntityB.class,
ChildEntityB.class,
ChildEntityA.class,
ParentEntityA.class,
}
)
@ServiceRegistry(
settings = {
@Setting(name = AvailableSettings.SHOW_SQL, value = "true"),
@Setting(name = AvailableSettings.FORMAT_SQL, value = "true"),
}
)
@SessionFactory
class ORMUnitTestCase {
@Test
void multipleEntitiesSameTableCascadeAll(SessionFactoryScope scope) {
scope.inTransaction(session -> {
ParentEntityA parentEntityA = new ParentEntityA("id");
ChildEntityA childEntityA = new ChildEntityA(parentEntityA);
parentEntityA.addChild(childEntityA);
session.persist(parentEntityA);
session.flush();
});
scope.inTransaction(session -> {
ParentEntityA terminal = session.find(ParentEntityA.class, "id");
terminal.getChildren().forEach(childEntityA -> childEntityA.setFlag(true));
});
}
}
@Entity
@Table(name = "PARENT")
class ParentEntityA {
@Id
@Column(name = "ID", nullable = false)
String id;
@OneToMany(mappedBy = "parent", cascade = ALL)
private final Set<ChildEntityA> children = new HashSet<>();
public ParentEntityA() {}
public ParentEntityA(String id) {
this.id = id;
}
public void addChild(ChildEntityA child) {
children.add(child);
}
public Set<ChildEntityA> getChildren() {
return children;
}
public String getId() {
return id;
}
}
@Entity
@Table(name = "CHILD")
class ChildEntityA {
@EmbeddedId
private ChildId childId;
@ManyToOne
@MapsId("parentId")
@JoinColumn(name = "PARENT_ID", referencedColumnName = "ID")
private ParentEntityA parent;
@Column(name = "FLAG", precision = 1)
private boolean flag;
public void setFlag(boolean flag) {
this.flag = flag;
}
public ChildEntityA() {}
public ChildEntityA(ParentEntityA parent) {
this.parent = parent;
this.childId = new ChildId(parent.getId());
}
}
@Embeddable
class ChildId {
@Column(name = "PARENT_ID", nullable = false)
private String parentId;
public ChildId() {}
public ChildId(String parentId) {
this.parentId = parentId;
}
}
// The entities B exist (and are registered in the DomainModel) but are not used
@Entity
@Table(name = "PARENT")
class ParentEntityB {
@Id
@Column(name = "ID", nullable = false)
String id;
@OneToMany(mappedBy = "parent")
private final Set<ChildEntityB> children = new HashSet<>();
public ParentEntityB() {}
}
@Entity
@Table(name = "CHILD")
class ChildEntityB {
@EmbeddedId
private ChildId childId;
@ManyToOne
@MapsId("parentId")
@JoinColumn(name = "PARENT_ID", referencedColumnName = "ID")
private ParentEntityB parent;
public ChildEntityB() {}
}
It seems that it has been introduced by HHH-18860. I get the same error with 7.1.24, 7.2.12 and 7.3.2. Last working version is 7.1.6.
I created an atlassian account for this but I am not been able to create an issue so I write here instead.
Is this expected but just not enforced in the older version or is this a bug ?