HHH-11859 - Fix PropertyAccessException on update of detached audited entity.

This commit is contained in:
Chris Cranford 2018-04-27 14:42:07 -04:00
parent adb9024c28
commit 6fb4ec0e02
1 changed files with 33 additions and 2 deletions

View File

@ -17,6 +17,8 @@ import org.hibernate.envers.internal.entities.mapper.id.IdMapper;
import org.hibernate.envers.internal.reader.AuditReaderImplementor;
import org.hibernate.envers.internal.tools.EntityTools;
import org.hibernate.envers.internal.tools.query.Parameters;
import org.hibernate.internal.util.compare.EqualsHelper;
import org.hibernate.persister.entity.EntityPersister;
/**
* @author Adam Warski (adam at warski dot org)
@ -81,8 +83,37 @@ public class ToOneIdMapper extends AbstractToOneMapper {
}
protected boolean checkModified(SessionImplementor session, Object newObj, Object oldObj) {
//noinspection SimplifiableConditionalExpression
return nonInsertableFake ? false : !EntityTools.entitiesEqual( session, referencedEntityName, newObj, oldObj );
if ( nonInsertableFake ) {
return false;
}
if ( newObj == null || oldObj == null || newObj.getClass().equals( oldObj.getClass() ) ) {
return !EntityTools.entitiesEqual( session, referencedEntityName, newObj, oldObj );
}
// There is a chance that oldObj may reference the identifier of the old entity rather
// than the entity instance itself. This happens under Session#update with a detached
// entity because the database snapshot that is used to derive the prior state doesn't
// return the entity instances of the to-one associations but only the identifier.
//
// So here we assume the method was supplied the id and we ask the persister to verify
// if the value is the identifier type. If not, we assume its the entity type and
// therefore resolve the identifier from the entity directly prior to simply then
// doing the identifier comparison.
final EntityPersister persister = session.getFactory().getMetamodel().entityPersister( referencedEntityName );
Object resolvedNewObjectId = newObj;
if ( !persister.getIdentifierType().getReturnedClass().isInstance( newObj ) ) {
resolvedNewObjectId = EntityTools.getIdentifier( session, referencedEntityName, newObj );
}
Object resolvedOldObjectId = oldObj;
if ( !persister.getIdentifierType().getReturnedClass().isInstance( oldObj ) ) {
resolvedOldObjectId = EntityTools.getIdentifier( session, referencedEntityName, oldObj );
}
return !EqualsHelper.areEqual( resolvedNewObjectId, resolvedOldObjectId );
}
@Override