From 9a335c1c04dca581caedb1e0b55c6ecf34d33433 Mon Sep 17 00:00:00 2001 From: Sanne Grinovero Date: Thu, 5 Aug 2021 22:12:56 +0100 Subject: [PATCH 1/4] HHH-14770 Optimise access to EntityPersister in Metamodel via Class type --- .../internal/StatelessSessionImpl.java | 13 ++++--- .../metamodel/internal/MetamodelImpl.java | 38 +++++++++++++------ 2 files changed, 34 insertions(+), 17 deletions(-) diff --git a/hibernate-core/src/main/java/org/hibernate/internal/StatelessSessionImpl.java b/hibernate-core/src/main/java/org/hibernate/internal/StatelessSessionImpl.java index 14cc081a13..c66a377b5a 100755 --- a/hibernate-core/src/main/java/org/hibernate/internal/StatelessSessionImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/internal/StatelessSessionImpl.java @@ -167,12 +167,12 @@ public class StatelessSessionImpl extends AbstractSharedSessionContract implemen @Override public Object get(Class entityClass, Serializable id) { - return get( entityClass.getName(), id ); + return get( entityClass, id, LockMode.NONE ); } @Override public Object get(Class entityClass, Serializable id, LockMode lockMode) { - return get( entityClass.getName(), id, lockMode ); + return get( getFactory().getMetamodel().entityPersister( entityClass ), id, lockMode ); } @Override @@ -182,10 +182,13 @@ public class StatelessSessionImpl extends AbstractSharedSessionContract implemen @Override public Object get(String entityName, Serializable id, LockMode lockMode) { + return get( getFactory().getMetamodel().entityPersister( entityName ), id, lockMode ); + } + + protected Object get(final EntityPersister ep, final Serializable id, final LockMode lockMode) { checkOpen(); - Object result = getFactory().getMetamodel().entityPersister( entityName ) - .load( id, null, getNullSafeLockMode( lockMode ), this ); + Object result = ep.load( id, null, getNullSafeLockMode( lockMode ), this ); if ( temporaryPersistenceContext.isLoadFinished() ) { temporaryPersistenceContext.clear(); } @@ -491,7 +494,7 @@ public class StatelessSessionImpl extends AbstractSharedSessionContract implemen throws HibernateException { checkOpen(); if ( entityName == null ) { - return getFactory().getMetamodel().entityPersister( guessEntityName( object ) ); + return getFactory().getMetamodel().entityPersister( object.getClass() ); } else { return getFactory().getMetamodel().entityPersister( entityName ).getSubclassEntityPersister( object, getFactory() ); diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/MetamodelImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/MetamodelImpl.java index 055485700e..60e16f220b 100755 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/MetamodelImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/MetamodelImpl.java @@ -142,6 +142,29 @@ public class MetamodelImpl implements MetamodelImplementor, Serializable { private final Map implementorsCache = new ConcurrentHashMap<>(); + // EntityPersister by Class is very hot: optimize access with a ClassValue + private final ClassValue entityPersisterMapByClass = new ClassValue() { + @Override + protected EntityPersister computeValue(final Class type) { + return entityPersisterMap.get( type.getName() ); + } + }; + + // "full location" of an EntityPersister by Class is also hot: optimize access with a ClassValue + private final ClassValue locateEntityPersisterMapByClass = new ClassValue() { + @Override + protected EntityPersister computeValue(final Class type) { + EntityPersister entityPersister = entityPersisterMapByClass.get( type ); + if ( entityPersister == null ) { + String mappedEntityName = entityProxyInterfaceMap.get( type ); + if ( mappedEntityName != null ) { + entityPersister = entityPersisterMap.get( mappedEntityName ); + } + } + return entityPersister; + } + }; + public MetamodelImpl(SessionFactoryImplementor sessionFactory, TypeConfiguration typeConfiguration) { this.sessionFactory = sessionFactory; this.typeConfiguration = typeConfiguration; @@ -694,7 +717,7 @@ public class MetamodelImpl implements MetamodelImplementor, Serializable { @Override public EntityPersister entityPersister(Class entityClass) { - return entityPersister( entityClass.getName() ); + return entityPersisterMapByClass.get( entityClass ); } @Override @@ -706,21 +729,12 @@ public class MetamodelImpl implements MetamodelImplementor, Serializable { return result; } - @Override - public EntityPersister locateEntityPersister(Class byClass) { - EntityPersister entityPersister = entityPersisterMap.get( byClass.getName() ); - if ( entityPersister == null ) { - String mappedEntityName = entityProxyInterfaceMap.get( byClass ); - if ( mappedEntityName != null ) { - entityPersister = entityPersisterMap.get( mappedEntityName ); - } - } - + public EntityPersister locateEntityPersister(final Class byClass) { + EntityPersister entityPersister = locateEntityPersisterMapByClass.get( byClass ); if ( entityPersister == null ) { throw new UnknownEntityTypeException( "Unable to locate persister: " + byClass.getName() ); } - return entityPersister; } From edcce3e1c22aa88ca60f69a90f438d8878b4ff87 Mon Sep 17 00:00:00 2001 From: Sanne Grinovero Date: Mon, 9 Aug 2021 11:45:40 +0100 Subject: [PATCH 2/4] HHH-14776 Promote method instantiate(EntityPersister, Serializable) from SessionImplementor to SharedSessionContractImplementor --- .../java/org/hibernate/engine/spi/SessionImplementor.java | 2 -- .../engine/spi/SharedSessionContractImplementor.java | 7 +++++++ .../java/org/hibernate/internal/StatelessSessionImpl.java | 7 ++++++- 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/hibernate-core/src/main/java/org/hibernate/engine/spi/SessionImplementor.java b/hibernate-core/src/main/java/org/hibernate/engine/spi/SessionImplementor.java index ac8e6acf3d..fcae06dbf6 100644 --- a/hibernate-core/src/main/java/org/hibernate/engine/spi/SessionImplementor.java +++ b/hibernate-core/src/main/java/org/hibernate/engine/spi/SessionImplementor.java @@ -78,8 +78,6 @@ public interface SessionImplementor ActionQueue getActionQueue(); - Object instantiate(EntityPersister persister, Serializable id) throws HibernateException; - void forceFlush(EntityEntry e) throws HibernateException; @Override diff --git a/hibernate-core/src/main/java/org/hibernate/engine/spi/SharedSessionContractImplementor.java b/hibernate-core/src/main/java/org/hibernate/engine/spi/SharedSessionContractImplementor.java index af3a118407..faf3394df4 100644 --- a/hibernate-core/src/main/java/org/hibernate/engine/spi/SharedSessionContractImplementor.java +++ b/hibernate-core/src/main/java/org/hibernate/engine/spi/SharedSessionContractImplementor.java @@ -333,6 +333,13 @@ public interface SharedSessionContractImplementor */ Object instantiate(String entityName, Serializable id) throws HibernateException; + /** + * Instantiate the entity class of an EntityPersister, initializing with the given identifier. + * This is more efficient than {@link #instantiate(String, Serializable)} but not always + * interchangeable: a single persister might be responsible for multiple types. + */ + Object instantiate(EntityPersister persister, Serializable id) throws HibernateException; + /** * Execute an SQL Query */ diff --git a/hibernate-core/src/main/java/org/hibernate/internal/StatelessSessionImpl.java b/hibernate-core/src/main/java/org/hibernate/internal/StatelessSessionImpl.java index c66a377b5a..9af5603814 100755 --- a/hibernate-core/src/main/java/org/hibernate/internal/StatelessSessionImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/internal/StatelessSessionImpl.java @@ -275,8 +275,13 @@ public class StatelessSessionImpl extends AbstractSharedSessionContract implemen public Object instantiate( String entityName, Serializable id) throws HibernateException { + return instantiate( getFactory().getMetamodel().entityPersister( entityName ), id ); + } + + @Override + public Object instantiate(EntityPersister persister, Serializable id) throws HibernateException { checkOpen(); - return getFactory().getMetamodel().entityPersister( entityName ).instantiate( id, this ); + return persister.instantiate( id, this ); } @Override From 135361a6b8c03144be3ffcc592962388ed14b61b Mon Sep 17 00:00:00 2001 From: Sanne Grinovero Date: Mon, 9 Aug 2021 14:23:04 +0100 Subject: [PATCH 3/4] HHH-14776 Optimise Loader operations by using the Persister directly --- .../src/main/java/org/hibernate/loader/Loader.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/hibernate-core/src/main/java/org/hibernate/loader/Loader.java b/hibernate-core/src/main/java/org/hibernate/loader/Loader.java index e00d06e3b3..85f572a7d1 100644 --- a/hibernate-core/src/main/java/org/hibernate/loader/Loader.java +++ b/hibernate-core/src/main/java/org/hibernate/loader/Loader.java @@ -1765,7 +1765,14 @@ public abstract class Loader { } else { // instantiate a new instance - object = session.instantiate( instanceClass, key.getIdentifier() ); + if ( persister.hasSubclasses() ) { + object = session.instantiate( instanceClass , key.getIdentifier() ); + } + else { + //When there are no subclasses, use the persister instance directly + //so to short-circuit the persister lookup: + object = session.instantiate( persister, key.getIdentifier() ); + } } //need to hydrate it. From fb0279e3a7e5e0daef1330aeb7cd2d17ff98cde2 Mon Sep 17 00:00:00 2001 From: Sanne Grinovero Date: Mon, 9 Aug 2021 16:09:34 +0100 Subject: [PATCH 4/4] HHH-14625 Avoid performing a ServiceRegistryLookup in JtaTransactionCoordinatorImpl constructor --- .../JtaTransactionCoordinatorBuilderImpl.java | 17 +++++++++++++++-- .../internal/JtaTransactionCoordinatorImpl.java | 5 +++-- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/hibernate-core/src/main/java/org/hibernate/resource/transaction/backend/jta/internal/JtaTransactionCoordinatorBuilderImpl.java b/hibernate-core/src/main/java/org/hibernate/resource/transaction/backend/jta/internal/JtaTransactionCoordinatorBuilderImpl.java index 412daf5b97..3320e50b9f 100644 --- a/hibernate-core/src/main/java/org/hibernate/resource/transaction/backend/jta/internal/JtaTransactionCoordinatorBuilderImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/resource/transaction/backend/jta/internal/JtaTransactionCoordinatorBuilderImpl.java @@ -6,11 +6,14 @@ */ package org.hibernate.resource.transaction.backend.jta.internal; +import org.hibernate.engine.transaction.jta.platform.spi.JtaPlatform; import org.hibernate.resource.jdbc.spi.PhysicalConnectionHandlingMode; import org.hibernate.resource.transaction.spi.DdlTransactionIsolator; import org.hibernate.resource.transaction.spi.TransactionCoordinator; import org.hibernate.resource.transaction.spi.TransactionCoordinatorBuilder; import org.hibernate.resource.transaction.spi.TransactionCoordinatorOwner; +import org.hibernate.service.spi.ServiceRegistryAwareService; +import org.hibernate.service.spi.ServiceRegistryImplementor; import org.hibernate.tool.schema.internal.exec.JdbcContext; /** @@ -18,15 +21,19 @@ import org.hibernate.tool.schema.internal.exec.JdbcContext; * * @author Steve Ebersole */ -public class JtaTransactionCoordinatorBuilderImpl implements TransactionCoordinatorBuilder { +public class JtaTransactionCoordinatorBuilderImpl implements TransactionCoordinatorBuilder, ServiceRegistryAwareService { + public static final String SHORT_NAME = "jta"; + private JtaPlatform jtaPlatform; + @Override public TransactionCoordinator buildTransactionCoordinator(TransactionCoordinatorOwner owner, Options options) { return new JtaTransactionCoordinatorImpl( this, owner, - options.shouldAutoJoinTransaction() + options.shouldAutoJoinTransaction(), + jtaPlatform ); } @@ -45,4 +52,10 @@ public class JtaTransactionCoordinatorBuilderImpl implements TransactionCoordina public DdlTransactionIsolator buildDdlTransactionIsolator(JdbcContext jdbcContext) { return new DdlTransactionIsolatorJtaImpl( jdbcContext ); } + + @Override + public void injectServices(ServiceRegistryImplementor serviceRegistry) { + this.jtaPlatform = serviceRegistry.getService( JtaPlatform.class ); + } + } diff --git a/hibernate-core/src/main/java/org/hibernate/resource/transaction/backend/jta/internal/JtaTransactionCoordinatorImpl.java b/hibernate-core/src/main/java/org/hibernate/resource/transaction/backend/jta/internal/JtaTransactionCoordinatorImpl.java index 13f2edaba5..3617c3f183 100644 --- a/hibernate-core/src/main/java/org/hibernate/resource/transaction/backend/jta/internal/JtaTransactionCoordinatorImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/resource/transaction/backend/jta/internal/JtaTransactionCoordinatorImpl.java @@ -74,14 +74,15 @@ public class JtaTransactionCoordinatorImpl implements TransactionCoordinator, Sy JtaTransactionCoordinatorImpl( TransactionCoordinatorBuilder transactionCoordinatorBuilder, TransactionCoordinatorOwner owner, - boolean autoJoinTransactions) { + boolean autoJoinTransactions, + JtaPlatform jtaPlatform) { this.transactionCoordinatorBuilder = transactionCoordinatorBuilder; this.transactionCoordinatorOwner = owner; this.autoJoinTransactions = autoJoinTransactions; final JdbcSessionContext jdbcSessionContext = owner.getJdbcSessionOwner().getJdbcSessionContext(); - this.jtaPlatform = jdbcSessionContext.getServiceRegistry().getService( JtaPlatform.class ); + this.jtaPlatform = jtaPlatform; final SessionFactoryOptions sessionFactoryOptions = jdbcSessionContext.getSessionFactory().getSessionFactoryOptions(); this.preferUserTransactions = sessionFactoryOptions.isPreferUserTransaction();