I did some debugging and it led me to this point:
Code:
MaterializedBlobType(AbstractStandardBasicType<T>).isEqual(Object, Object) line: 195
MaterializedBlobType(AbstractStandardBasicType<T>).getReplacement(T, T, SharedSessionContractImplementor) line: 75
MaterializedBlobType(AbstractStandardBasicType<T>).replace(Object, Object, SharedSessionContractImplementor, Object, Map, ForeignKeyDirection) line: 361
TypeHelper.replace(Object[], Object[], Type[], SharedSessionContractImplementor, Object, Map, ForeignKeyDirection) line: 211
DefaultMergeEventListener.copyValues(EntityPersister, Object, Object, SessionImplementor, Map, ForeignKeyDirection) line: 430
DefaultMergeEventListener.entityIsTransient(MergeEvent, Map) line: 232
DefaultMergeEventListener.onMerge(MergeEvent, Map) line: 172
SessionImpl.fireMerge(Map, MergeEvent) line: 886
SessionImpl.merge(String, Object, Map) line: 853
CascadingActions$6.cascade(EventSource, Object, String, Object, boolean) line: 261
Cascade.cascadeToOne(CascadingAction, EventSource, Object, Object, Type, CascadeStyle, Object, boolean) line: 391
Cascade.cascadeAssociation(CascadingAction, CascadePoint, EventSource, int, Object, Object, Type, CascadeStyle, Object, boolean) line: 316
Cascade.cascadeProperty(CascadingAction, CascadePoint, EventSource, int, Object, Object, Type, CascadeStyle, String, Object, boolean) line: 155
Cascade.cascade(CascadingAction, CascadePoint, EventSource, EntityPersister, Object, Object) line: 104
DefaultMergeEventListener(AbstractSaveEventListener).cascadeAfterSave(EventSource, EntityPersister, Object, Object) line: 445
DefaultMergeEventListener.entityIsTransient(MergeEvent, Map) line: 238
DefaultMergeEventListener.onMerge(MergeEvent, Map) line: 172
DefaultMergeEventListener.onMerge(MergeEvent) line: 68
SessionImpl.fireMerge(MergeEvent) line: 862
SessionImpl.merge(String, Object) line: 843
SessionImpl.merge(Object) line: 848
HibernateTemplate$22.doInHibernate(Session) line: 782
At the point (MaterializedBlobType(AbstractStandardBasicType<T>).getReplacement(T, T, SharedSessionContractImplementor) line: 75 )
Code:
protected T getReplacement(T original, T target, SharedSessionContractImplementor session) {
if ( !isMutable() ) {
return original;
}
else if ( isEqual( original, target ) ) {
return original;
}
else {
return deepCopy( original );
}
}
original - is the actual byte[] array I'm trying to persist
target = org.hibernate.bytecode.enhance.spi.LazyPropertyInitializer.UNFETCHED_PROPERTY
After it goes on the branch isEqual( original, target ) and of course the 2 objects are not equal.
Maybe a solution would be to modify the following method ? org.hibernate.type.TypeHelper.replace(Object[], Object[], Type[], SharedSessionContractImplementor, Object, Map, ForeignKeyDirection))
by adding a condition like you did when fixing the other
Code:
else if ( target[i] == LazyPropertyInitializer.UNFETCHED_PROPERTY ) {
if ( types[i].isMutable() ) {
copied[i] = types[i].deepCopy( original[i], session.getFactory() );
}
else {
copied[i] = original[i];
}
}
just as you did with the other one: org.hibernate.type.TypeHelper.replace(Object[], Object[], Type[], SharedSessionContractImplementor, Object, Map) in pull 891
https://github.com/hibernate/hibernate-orm/pull/891/filesI think this method is called for MyEntity properties (org.hibernate.type.TypeHelper.replace(Object[], Object[], Type[], SharedSessionContractImplementor, Object, Map, ForeignKeyDirection))) because I am persisting MyEntity indirectly through a parent entity MyContainerEntity (one-to-one relation, MyEntity being the owning side).
So the particularity of this case is that that a child entity fails to get merged through a parent entity. The child entity is compile time instrumented and has a LAZY Basic attribute/property.