From 481f0e3c369a52df5ae753b6dda9999da3016a30 Mon Sep 17 00:00:00 2001 From: Sanne Grinovero Date: Sat, 22 Feb 2014 00:02:30 +0000 Subject: [PATCH] HHH-8991 Cache lookup of identifier Type and associated EntityPersister for each EntityType --- .../java/org/hibernate/type/EntityType.java | 67 +++++++++++++++---- .../org/hibernate/type/ManyToOneType.java | 4 +- 2 files changed, 57 insertions(+), 14 deletions(-) diff --git a/hibernate-core/src/main/java/org/hibernate/type/EntityType.java b/hibernate-core/src/main/java/org/hibernate/type/EntityType.java index 28e32b46e1..8b0b4ec585 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/EntityType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/EntityType.java @@ -62,6 +62,19 @@ public abstract class EntityType extends AbstractType implements AssociationType private final boolean unwrapProxy; private final boolean referenceToPrimaryKey; + /** + * Cached because of performance + * @see #getIdentifierType(SessionImplementor) + * @see #getIdentifierType(Mapping) + */ + private transient volatile Type associatedIdentifierType; + + /** + * Cached because of performance + * @see #getAssociatedEntityPersister + */ + private transient volatile EntityPersister associatedEntityPersister; + private transient Class returnedClass; /** @@ -240,7 +253,7 @@ public abstract class EntityType extends AbstractType implements AssociationType * @throws MappingException Generally indicates an invalid entity name. */ public Joinable getAssociatedJoinable(SessionFactoryImplementor factory) throws MappingException { - return ( Joinable ) factory.getEntityPersister( associatedEntityName ); + return ( Joinable ) getAssociatedEntityPersister( factory ); } /** @@ -359,7 +372,7 @@ public abstract class EntityType extends AbstractType implements AssociationType * {@inheritDoc} */ public int getHashCode(Object x, SessionFactoryImplementor factory) { - EntityPersister persister = factory.getEntityPersister(associatedEntityName); + EntityPersister persister = getAssociatedEntityPersister( factory ); if ( !persister.canExtractIdOutOfEntity() ) { return super.getHashCode( x ); } @@ -387,7 +400,7 @@ public abstract class EntityType extends AbstractType implements AssociationType return x == y; } - EntityPersister persister = factory.getEntityPersister(associatedEntityName); + EntityPersister persister = getAssociatedEntityPersister( factory ); if ( !persister.canExtractIdOutOfEntity() ) { return super.isEqual(x, y ); } @@ -497,7 +510,21 @@ public abstract class EntityType extends AbstractType implements AssociationType } public Type getSemiResolvedType(SessionFactoryImplementor factory) { - return factory.getEntityPersister( associatedEntityName ).getIdentifierType(); + return getAssociatedEntityPersister( factory ).getIdentifierType(); + } + + protected EntityPersister getAssociatedEntityPersister(final SessionFactoryImplementor factory) { + final EntityPersister persister = associatedEntityPersister; + //The following branch implements a simple lazy-initialization, but rather than the canonical + //form it returns the local variable to avoid a second volatile read: associatedEntityPersister + //needs to be volatile as the initialization might happen by a different thread than the readers. + if ( persister == null ) { + associatedEntityPersister = factory.getEntityPersister( getAssociatedEntityName() ); + return associatedEntityPersister; + } + else { + return persister; + } } protected final Object getIdentifier(Object value, SessionImplementor session) throws HibernateException { @@ -512,7 +539,7 @@ public abstract class EntityType extends AbstractType implements AssociationType return null; } else { - EntityPersister entityPersister = session.getFactory().getEntityPersister( getAssociatedEntityName() ); + EntityPersister entityPersister = getAssociatedEntityPersister( session.getFactory() ); Object propertyValue = entityPersister.getPropertyValue( value, uniqueKeyPropertyName ); // We now have the value of the property-ref we reference. However, // we need to dig a little deeper, as that property might also be @@ -549,7 +576,7 @@ public abstract class EntityType extends AbstractType implements AssociationType return "null"; } - EntityPersister persister = factory.getEntityPersister( associatedEntityName ); + EntityPersister persister = getAssociatedEntityPersister( factory ); StringBuilder result = new StringBuilder().append( associatedEntityName ); if ( persister.hasIdentifierProperty() ) { @@ -597,8 +624,18 @@ public abstract class EntityType extends AbstractType implements AssociationType * @param factory The mappings... * @return The identifier type */ - Type getIdentifierType(Mapping factory) { - return factory.getIdentifierType( getAssociatedEntityName() ); + Type getIdentifierType(final Mapping factory) { + final Type type = associatedIdentifierType; + //The following branch implements a simple lazy-initialization, but rather than the canonical + //form it returns the local variable to avoid a second volatile read: associatedIdentifierType + //needs to be volatile as the initialization might happen by a different thread than the readers. + if ( type == null ) { + associatedIdentifierType = factory.getIdentifierType( getAssociatedEntityName() ); + return associatedIdentifierType; + } + else { + return type; + } } /** @@ -607,8 +644,15 @@ public abstract class EntityType extends AbstractType implements AssociationType * @param session The originating session * @return The identifier type */ - Type getIdentifierType(SessionImplementor session) { - return getIdentifierType( session.getFactory() ); + Type getIdentifierType(final SessionImplementor session) { + final Type type = associatedIdentifierType; + if ( type == null ) { + associatedIdentifierType = getIdentifierType( session.getFactory() ); + return associatedIdentifierType; + } + else { + return type; + } } /** @@ -664,8 +708,7 @@ public abstract class EntityType extends AbstractType implements AssociationType */ protected final Object resolveIdentifier(Serializable id, SessionImplementor session) throws HibernateException { boolean isProxyUnwrapEnabled = unwrapProxy && - session.getFactory() - .getEntityPersister( getAssociatedEntityName() ) + getAssociatedEntityPersister( session.getFactory() ) .isInstrumented(); Object proxyOrEntity = session.internalLoad( diff --git a/hibernate-core/src/main/java/org/hibernate/type/ManyToOneType.java b/hibernate-core/src/main/java/org/hibernate/type/ManyToOneType.java index 63c76af840..3b2bae54d2 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/ManyToOneType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/ManyToOneType.java @@ -200,7 +200,7 @@ public class ManyToOneType extends EntityType { private void scheduleBatchLoadIfNeeded(Serializable id, SessionImplementor session) throws MappingException { //cannot batch fetch by unique key (property-ref associations) if ( uniqueKeyPropertyName == null && id != null ) { - final EntityPersister persister = session.getFactory().getEntityPersister( getAssociatedEntityName() ); + final EntityPersister persister = getAssociatedEntityPersister( session.getFactory() ); if ( persister.isBatchLoadable() ) { final EntityKey entityKey = session.generateEntityKey( id, persister ); if ( !session.getPersistenceContext().containsEntity( entityKey ) ) { @@ -209,7 +209,7 @@ public class ManyToOneType extends EntityType { } } } - + public boolean useLHSPrimaryKey() { return false; }