HHH-16052 EntityKey and CollectionKey equality optimisation

This commit is contained in:
Sanne Grinovero 2023-01-16 12:27:17 +00:00 committed by Sanne Grinovero
parent cf65a2d275
commit 67dc1ed835
5 changed files with 24 additions and 7 deletions

View File

@ -11,6 +11,7 @@ import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import org.hibernate.AssertionFailure;
import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.pretty.MessageHelper;
import org.hibernate.type.Type;
@ -42,6 +43,9 @@ public final class CollectionKey implements Serializable {
Type keyType,
SessionFactoryImplementor factory) {
this.role = role;
if ( key == null ) {
throw new AssertionFailure( "null identifier for collection of role (" + role + ")" );
}
this.key = key;
this.keyType = keyType;
this.factory = factory;
@ -73,17 +77,18 @@ public final class CollectionKey implements Serializable {
}
@Override
public boolean equals(Object other) {
public boolean equals(final Object other) {
if ( this == other ) {
return true;
}
if ( other == null || getClass() != other.getClass() ) {
if ( other == null || CollectionKey.class != other.getClass() ) {
return false;
}
final CollectionKey that = (CollectionKey) other;
return that.role.equals( role )
&& keyType.isEqual( that.key, key, factory );
&& ( this.key == that.key ||
keyType.isEqual( this.key, that.key, factory ) );
}
@Override

View File

@ -97,7 +97,8 @@ public final class EntityKey implements Serializable {
}
private boolean sameIdentifier(final EntityKey otherKey) {
return persister.getIdentifierType().isEqual( otherKey.identifier, this.identifier, persister.getFactory() );
return this.identifier == otherKey.identifier ||
persister.getIdentifierType().isEqual( otherKey.identifier, this.identifier, persister.getFactory() );
}
private boolean samePersistentType(final EntityKey otherKey) {

View File

@ -82,6 +82,13 @@ public class DefaultFlushEntityEventListener implements FlushEntityEventListener
+ " entry (don't flush the Session after an exception occurs)" );
}
//Small optimisation: always try to avoid getIdentifierType().isEqual(..) when possible.
//(However it's not safe to invoke the equals() method as it might trigger side-effects)
if ( id == oid ) {
//No further checks necessary:
return;
}
if ( !persister.getIdentifierType().isEqual( id, oid, session.getFactory() ) ) {
throw new HibernateException( "identifier of an instance of " + persister.getEntityName()
+ " was altered from " + oid + " to " + id );

View File

@ -165,7 +165,8 @@ public abstract class AbstractStandardBasicType<T>
@Override
@SuppressWarnings("unchecked")
public boolean isEqual(Object one, Object another) {
return javaType.areEqual( (T) one, (T) another );
return ( one == another ) //optimisation to attempt avoid the need for the method on javaType:
|| javaType.areEqual( (T) one, (T) another );
}
@Override

View File

@ -363,6 +363,9 @@ public abstract class EntityType extends AbstractType implements AssociationType
if ( x == null || y == null ) {
return x == y;
}
if ( x == y ) {
return true;
}
final EntityPersister persister = getAssociatedEntityPersister( factory );
final Class<?> mappedClass = persister.getMappedClass();
@ -396,8 +399,8 @@ public abstract class EntityType extends AbstractType implements AssociationType
}
}
return persister.getIdentifierType()
.isEqual( xid, yid, factory );
// Check for reference equality first as the type-specific checks by IdentifierType are sometimes non-trivial
return ( xid == yid ) || persister.getIdentifierType().isEqual( xid, yid, factory );
}
/**