Here's the issue:
On the lock, the natural id reattachment must use a database snapshot, since the natural id is mutable. Your B entity has 2 natural ids: one using ManyToOnType and the other IntegerType. The reattachment uses this stack:
{code} ManyToOneType.hydrate(ResultSet, String[], SessionImplementor, Object) line: 190 SingleTableEntityPersister(AbstractEntityPersister).getDatabaseSnapshot(Serializable, SessionImplementor) line: 1534 StatefulPersistenceContext.getDatabaseSnapshot(Serializable, EntityPersister) line: 316 SingleTableEntityPersister(AbstractEntityPersister).handleNaturalIdReattachment(Object, SessionImplementor) line: 4248 SingleTableEntityPersister(AbstractEntityPersister).afterReassociate(Object, SessionImplementor) line: 4228 DefaultLockEventListener(AbstractReassociateEventListener).reassociate(AbstractEvent, Object, Serializable, EntityPersister) line: 100 DefaultLockEventListener.onLock(LockEvent) line: 95 SessionImpl.fireLock(LockEvent) line: 819 SessionImpl.fireLock(Object, LockOptions) line: 812 SessionImpl.access$11(SessionImpl, Object, LockOptions) line: 811 SessionImpl$LockRequestImpl.lock(Object) line: 2438 ... {code}
ManyToOneType#hydrate does not return the actual A entity (associations aren't resolved) -- instead, it returns the FK Long value. The hydrated values are later used by the following stack. ManyToOneType#disassemble is called, assuming the value is the A entity. It fails when the Long is there instead.
{code} DirectPropertyAccessor$DirectGetter.get(Object) line: 62 PojoEntityTuplizer(AbstractEntityTuplizer).getIdentifier(Object, SessionImplementor) line: 345 SingleTableEntityPersister(AbstractEntityPersister).getIdentifier(Object, SessionImplementor) line: 4547 SingleTableEntityPersister(AbstractEntityPersister).isTransient(Object, SessionImplementor) line: 4269 ForeignKeys.isTransient(String, Object, Boolean, SessionImplementor) line: 243 ForeignKeys.getEntityIdentifierIfNotUnsaved(String, Object, SessionImplementor) line: 293 ManyToOneType.disassemble(Object, SessionImplementor, Object) line: 247 NaturalIdCacheKey.<init>(Object[], EntityPersister, SessionImplementor) line: 84 StatefulPersistenceContext$1.removeSharedNaturalIdCrossReference(EntityPersister, Serializable, Object[]) line: 1825 SingleTableEntityPersister(AbstractEntityPersister).handleNaturalIdReattachment(Object, SessionImplementor) line: 4256 SingleTableEntityPersister(AbstractEntityPersister).afterReassociate(Object, SessionImplementor) line: 4228 DefaultLockEventListener(AbstractReassociateEventListener).reassociate(AbstractEvent, Object, Serializable, EntityPersister) line: 100 DefaultLockEventListener.onLock(LockEvent) line: 95 SessionImpl.fireLock(LockEvent) line: 819 SessionImpl.fireLock(Object, LockOptions) line: 812 SessionImpl.access$11(SessionImpl, Object, LockOptions) line: 811 SessionImpl$LockRequestImpl.lock(Object) line: 2438 ... {code}
|