HHH-16728 Optimise iteration of AssociationType properties within a Persister
This commit is contained in:
parent
0d58a2410c
commit
2b92c3dbe5
|
@ -120,6 +120,7 @@ import org.hibernate.internal.util.IndexedConsumer;
|
|||
import org.hibernate.internal.util.LazyValue;
|
||||
import org.hibernate.internal.util.StringHelper;
|
||||
import org.hibernate.internal.util.collections.ArrayHelper;
|
||||
import org.hibernate.internal.util.collections.CollectionHelper;
|
||||
import org.hibernate.internal.util.collections.LockModeEnumMap;
|
||||
import org.hibernate.jdbc.Expectation;
|
||||
import org.hibernate.jdbc.TooManyRowsAffectedException;
|
||||
|
@ -279,6 +280,7 @@ import org.hibernate.stat.spi.StatisticsImplementor;
|
|||
import org.hibernate.tuple.NonIdentifierAttribute;
|
||||
import org.hibernate.tuple.entity.EntityMetamodel;
|
||||
import org.hibernate.type.AnyType;
|
||||
import org.hibernate.type.AssociationType;
|
||||
import org.hibernate.type.BasicType;
|
||||
import org.hibernate.type.CollectionType;
|
||||
import org.hibernate.type.CompositeType;
|
||||
|
@ -464,6 +466,8 @@ public abstract class AbstractEntityPersister
|
|||
|
||||
private final boolean implementsLifecycle;
|
||||
|
||||
private List<UniqueKeyEntry> uniqueKeyEntries = null; //lazily initialized
|
||||
|
||||
@Deprecated(since = "6.0")
|
||||
public AbstractEntityPersister(
|
||||
final PersistentClass persistentClass,
|
||||
|
@ -1166,6 +1170,30 @@ public abstract class AbstractEntityPersister
|
|||
return useReferenceCacheEntries;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<UniqueKeyEntry> uniqueKeyEntries() {
|
||||
if ( this.uniqueKeyEntries == null ) {
|
||||
this.uniqueKeyEntries = initUniqueKeyEntries( this );
|
||||
}
|
||||
return this.uniqueKeyEntries;
|
||||
}
|
||||
|
||||
private static List<UniqueKeyEntry> initUniqueKeyEntries(final AbstractEntityPersister aep) {
|
||||
ArrayList<UniqueKeyEntry> uniqueKeys = new ArrayList();
|
||||
for ( Type propertyType : aep.getPropertyTypes() ) {
|
||||
if ( propertyType instanceof AssociationType ) {
|
||||
final AssociationType associationType = (AssociationType) propertyType;
|
||||
final String ukName = associationType.getLHSPropertyName();
|
||||
if ( ukName != null ) {
|
||||
final int index = aep.findAttributeMapping( ukName ).getStateArrayPosition();
|
||||
final Type type = aep.getPropertyTypes()[index];
|
||||
uniqueKeys.add( new UniqueKeyEntry( ukName, index, type ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
return CollectionHelper.toSmallList( uniqueKeys );
|
||||
}
|
||||
|
||||
protected Map<String, SingleIdArrayLoadPlan> getLazyLoadPlanByFetchGroup() {
|
||||
final BytecodeEnhancementMetadata metadata = entityMetamodel.getBytecodeEnhancementMetadata();
|
||||
return metadata.isEnhancedForLazyLoading() && metadata.getLazyAttributesMetadata().hasLazyAttributes()
|
||||
|
|
|
@ -12,6 +12,7 @@ import java.util.Map;
|
|||
import java.util.function.Consumer;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.Incubating;
|
||||
import org.hibernate.LockMode;
|
||||
import org.hibernate.LockOptions;
|
||||
import org.hibernate.MappingException;
|
||||
|
@ -1075,4 +1076,10 @@ public interface EntityPersister extends EntityMappingType, RootTableGroupProduc
|
|||
@Deprecated(since = "6.2")
|
||||
String ENTITY_ID = "id";
|
||||
|
||||
/**
|
||||
* @return Metadata for each unique key defined
|
||||
*/
|
||||
@Incubating
|
||||
Iterable<UniqueKeyEntry> uniqueKeyEntries();
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||
*/
|
||||
package org.hibernate.persister.entity;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import org.hibernate.type.Type;
|
||||
|
||||
/**
|
||||
* Useful metadata representing a unique key within a Persister
|
||||
*/
|
||||
public final class UniqueKeyEntry {
|
||||
|
||||
private final String uniqueKeyName;
|
||||
private final int stateArrayPosition;
|
||||
private final Type propertyType;
|
||||
|
||||
public UniqueKeyEntry(final String uniqueKeyName, final int stateArrayPosition, final Type propertyType) {
|
||||
this.uniqueKeyName = Objects.requireNonNull( uniqueKeyName );
|
||||
this.stateArrayPosition = stateArrayPosition;
|
||||
this.propertyType = Objects.requireNonNull( propertyType );
|
||||
}
|
||||
|
||||
public String getUniqueKeyName() {
|
||||
return this.uniqueKeyName;
|
||||
}
|
||||
|
||||
public int getStateArrayPosition() {
|
||||
return this.stateArrayPosition;
|
||||
}
|
||||
|
||||
public Type getPropertyType() {
|
||||
return this.propertyType;
|
||||
}
|
||||
|
||||
}
|
|
@ -41,6 +41,7 @@ import org.hibernate.metamodel.mapping.EntityVersionMapping;
|
|||
import org.hibernate.metamodel.mapping.ManagedMappingType;
|
||||
import org.hibernate.metamodel.mapping.ModelPart;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
import org.hibernate.persister.entity.UniqueKeyEntry;
|
||||
import org.hibernate.property.access.internal.PropertyAccessStrategyBackRefImpl;
|
||||
import org.hibernate.proxy.LazyInitializer;
|
||||
import org.hibernate.proxy.map.MapProxy;
|
||||
|
@ -1034,32 +1035,27 @@ public abstract class AbstractEntityInitializer extends AbstractFetchParentAcces
|
|||
}
|
||||
}
|
||||
|
||||
protected void registerPossibleUniqueKeyEntries(Object toInitialize, SharedSessionContractImplementor session) {
|
||||
for ( Type propertyType : concreteDescriptor.getPropertyTypes() ) {
|
||||
if ( propertyType instanceof AssociationType ) {
|
||||
final AssociationType associationType = (AssociationType) propertyType;
|
||||
final String ukName = associationType.getLHSPropertyName();
|
||||
if ( ukName != null ) {
|
||||
final int index = concreteDescriptor.findAttributeMapping( ukName ).getStateArrayPosition();
|
||||
final Type type = concreteDescriptor.getPropertyTypes()[index];
|
||||
protected void registerPossibleUniqueKeyEntries(final Object toInitialize, final SharedSessionContractImplementor session) {
|
||||
for ( UniqueKeyEntry entry : concreteDescriptor.uniqueKeyEntries() ) {
|
||||
final String ukName = entry.getUniqueKeyName();
|
||||
final int index = entry.getStateArrayPosition();//concreteDescriptor.findAttributeMapping( ukName ).getStateArrayPosition();
|
||||
final Type type = entry.getPropertyType();//concreteDescriptor.getPropertyTypes()[index];
|
||||
|
||||
// polymorphism not really handled completely correctly,
|
||||
// perhaps...well, actually its ok, assuming that the
|
||||
// entity name used in the lookup is the same as the
|
||||
// one used here, which it will be
|
||||
// polymorphism not really handled completely correctly,
|
||||
// perhaps...well, actually its ok, assuming that the
|
||||
// entity name used in the lookup is the same as the
|
||||
// one used here, which it will be
|
||||
|
||||
if ( resolvedEntityState[index] != null ) {
|
||||
final EntityUniqueKey euk = new EntityUniqueKey(
|
||||
concreteDescriptor.getRootEntityDescriptor().getEntityName(),
|
||||
//polymorphism comment above
|
||||
ukName,
|
||||
resolvedEntityState[index],
|
||||
type,
|
||||
session.getFactory()
|
||||
);
|
||||
session.getPersistenceContextInternal().addEntity( euk, toInitialize );
|
||||
}
|
||||
}
|
||||
if ( resolvedEntityState[index] != null ) {
|
||||
final EntityUniqueKey euk = new EntityUniqueKey(
|
||||
concreteDescriptor.getRootEntityDescriptor().getEntityName(),
|
||||
//polymorphism comment above
|
||||
ukName,
|
||||
resolvedEntityState[index],
|
||||
type,
|
||||
session.getFactory()
|
||||
);
|
||||
session.getPersistenceContextInternal().addEntity( euk, toInitialize );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -60,6 +60,7 @@ import org.hibernate.metamodel.model.domain.NavigableRole;
|
|||
import org.hibernate.metamodel.spi.EntityRepresentationStrategy;
|
||||
import org.hibernate.persister.collection.CollectionPersister;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
import org.hibernate.persister.entity.UniqueKeyEntry;
|
||||
import org.hibernate.persister.spi.PersisterClassResolver;
|
||||
import org.hibernate.persister.spi.PersisterCreationContext;
|
||||
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableInsertStrategy;
|
||||
|
@ -758,6 +759,11 @@ public class GoofyPersisterClassProvider implements PersisterClassResolver {
|
|||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<UniqueKeyEntry> uniqueKeyEntries() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAffectedByEnabledFilters(LoadQueryInfluencers influencers) {
|
||||
return false;
|
||||
|
|
|
@ -58,6 +58,7 @@ import org.hibernate.metamodel.spi.EntityRepresentationStrategy;
|
|||
import org.hibernate.orm.test.jpa.SettingsGenerator;
|
||||
import org.hibernate.persister.collection.CollectionPersister;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
import org.hibernate.persister.entity.UniqueKeyEntry;
|
||||
import org.hibernate.persister.internal.PersisterClassResolverInitiator;
|
||||
import org.hibernate.persister.spi.PersisterClassResolver;
|
||||
import org.hibernate.persister.spi.PersisterCreationContext;
|
||||
|
@ -729,6 +730,11 @@ public class PersisterClassProviderTest {
|
|||
return false; //To change body of implemented methods use File | Settings | File Templates.
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<UniqueKeyEntry> uniqueKeyEntries() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CacheEntry buildCacheEntry(Object entity, Object[] state, Object version, SharedSessionContractImplementor session) {
|
||||
return null;
|
||||
|
|
|
@ -57,6 +57,7 @@ import org.hibernate.metamodel.mapping.TableDetails;
|
|||
import org.hibernate.metamodel.model.domain.NavigableRole;
|
||||
import org.hibernate.metamodel.spi.EntityRepresentationStrategy;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
import org.hibernate.persister.entity.UniqueKeyEntry;
|
||||
import org.hibernate.persister.spi.PersisterCreationContext;
|
||||
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableInsertStrategy;
|
||||
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy;
|
||||
|
@ -849,6 +850,11 @@ public class CustomPersister implements EntityPersister {
|
|||
return false; //To change body of implemented methods use File | Settings | File Templates.
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<UniqueKeyEntry> uniqueKeyEntries() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAffectedByEntityGraph(LoadQueryInfluencers loadQueryInfluencers) {
|
||||
return loadQueryInfluencers.getEffectiveEntityGraph().getGraph() != null;
|
||||
|
|
Loading…
Reference in New Issue