HHH-16728 Optimise iteration of AssociationType properties within a Persister
This commit is contained in:
parent
7f003150da
commit
64216dd2c9
|
@ -116,6 +116,7 @@ import org.hibernate.internal.util.IndexedConsumer;
|
||||||
import org.hibernate.internal.util.LazyValue;
|
import org.hibernate.internal.util.LazyValue;
|
||||||
import org.hibernate.internal.util.StringHelper;
|
import org.hibernate.internal.util.StringHelper;
|
||||||
import org.hibernate.internal.util.collections.ArrayHelper;
|
import org.hibernate.internal.util.collections.ArrayHelper;
|
||||||
|
import org.hibernate.internal.util.collections.CollectionHelper;
|
||||||
import org.hibernate.internal.util.collections.LockModeEnumMap;
|
import org.hibernate.internal.util.collections.LockModeEnumMap;
|
||||||
import org.hibernate.jdbc.Expectation;
|
import org.hibernate.jdbc.Expectation;
|
||||||
import org.hibernate.jdbc.TooManyRowsAffectedException;
|
import org.hibernate.jdbc.TooManyRowsAffectedException;
|
||||||
|
@ -272,6 +273,7 @@ import org.hibernate.stat.spi.StatisticsImplementor;
|
||||||
import org.hibernate.tuple.NonIdentifierAttribute;
|
import org.hibernate.tuple.NonIdentifierAttribute;
|
||||||
import org.hibernate.tuple.entity.EntityMetamodel;
|
import org.hibernate.tuple.entity.EntityMetamodel;
|
||||||
import org.hibernate.type.AnyType;
|
import org.hibernate.type.AnyType;
|
||||||
|
import org.hibernate.type.AssociationType;
|
||||||
import org.hibernate.type.BasicType;
|
import org.hibernate.type.BasicType;
|
||||||
import org.hibernate.type.CollectionType;
|
import org.hibernate.type.CollectionType;
|
||||||
import org.hibernate.type.CompositeType;
|
import org.hibernate.type.CompositeType;
|
||||||
|
@ -458,6 +460,8 @@ public abstract class AbstractEntityPersister
|
||||||
|
|
||||||
private final boolean implementsLifecycle;
|
private final boolean implementsLifecycle;
|
||||||
|
|
||||||
|
private List<UniqueKeyEntry> uniqueKeyEntries = null; //lazily initialized
|
||||||
|
|
||||||
@Deprecated(since = "6.0")
|
@Deprecated(since = "6.0")
|
||||||
public AbstractEntityPersister(
|
public AbstractEntityPersister(
|
||||||
final PersistentClass persistentClass,
|
final PersistentClass persistentClass,
|
||||||
|
@ -1161,6 +1165,30 @@ public abstract class AbstractEntityPersister
|
||||||
return useReferenceCacheEntries;
|
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() {
|
protected Map<String, SingleIdArrayLoadPlan> getLazyLoadPlanByFetchGroup() {
|
||||||
final BytecodeEnhancementMetadata metadata = entityMetamodel.getBytecodeEnhancementMetadata();
|
final BytecodeEnhancementMetadata metadata = entityMetamodel.getBytecodeEnhancementMetadata();
|
||||||
return metadata.isEnhancedForLazyLoading() && metadata.getLazyAttributesMetadata().hasLazyAttributes()
|
return metadata.isEnhancedForLazyLoading() && metadata.getLazyAttributesMetadata().hasLazyAttributes()
|
||||||
|
|
|
@ -12,6 +12,7 @@ import java.util.Map;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
import org.hibernate.HibernateException;
|
import org.hibernate.HibernateException;
|
||||||
|
import org.hibernate.Incubating;
|
||||||
import org.hibernate.LockMode;
|
import org.hibernate.LockMode;
|
||||||
import org.hibernate.LockOptions;
|
import org.hibernate.LockOptions;
|
||||||
import org.hibernate.MappingException;
|
import org.hibernate.MappingException;
|
||||||
|
@ -1096,4 +1097,10 @@ public interface EntityPersister extends EntityMappingType, RootTableGroupProduc
|
||||||
@Deprecated(since = "6.2")
|
@Deprecated(since = "6.2")
|
||||||
String ENTITY_ID = "id";
|
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.ManagedMappingType;
|
||||||
import org.hibernate.metamodel.mapping.ModelPart;
|
import org.hibernate.metamodel.mapping.ModelPart;
|
||||||
import org.hibernate.persister.entity.EntityPersister;
|
import org.hibernate.persister.entity.EntityPersister;
|
||||||
|
import org.hibernate.persister.entity.UniqueKeyEntry;
|
||||||
import org.hibernate.property.access.internal.PropertyAccessStrategyBackRefImpl;
|
import org.hibernate.property.access.internal.PropertyAccessStrategyBackRefImpl;
|
||||||
import org.hibernate.proxy.LazyInitializer;
|
import org.hibernate.proxy.LazyInitializer;
|
||||||
import org.hibernate.proxy.map.MapProxy;
|
import org.hibernate.proxy.map.MapProxy;
|
||||||
|
@ -1017,14 +1018,11 @@ public abstract class AbstractEntityInitializer extends AbstractFetchParentAcces
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void registerPossibleUniqueKeyEntries(Object toInitialize, SharedSessionContractImplementor session) {
|
protected void registerPossibleUniqueKeyEntries(final Object toInitialize, final SharedSessionContractImplementor session) {
|
||||||
for ( Type propertyType : concreteDescriptor.getPropertyTypes() ) {
|
for ( UniqueKeyEntry entry : concreteDescriptor.uniqueKeyEntries() ) {
|
||||||
if ( propertyType instanceof AssociationType ) {
|
final String ukName = entry.getUniqueKeyName();
|
||||||
final AssociationType associationType = (AssociationType) propertyType;
|
final int index = entry.getStateArrayPosition();//concreteDescriptor.findAttributeMapping( ukName ).getStateArrayPosition();
|
||||||
final String ukName = associationType.getLHSPropertyName();
|
final Type type = entry.getPropertyType();//concreteDescriptor.getPropertyTypes()[index];
|
||||||
if ( ukName != null ) {
|
|
||||||
final int index = concreteDescriptor.findAttributeMapping( ukName ).getStateArrayPosition();
|
|
||||||
final Type type = concreteDescriptor.getPropertyTypes()[index];
|
|
||||||
|
|
||||||
// polymorphism not really handled completely correctly,
|
// polymorphism not really handled completely correctly,
|
||||||
// perhaps...well, actually its ok, assuming that the
|
// perhaps...well, actually its ok, assuming that the
|
||||||
|
@ -1044,8 +1042,6 @@ public abstract class AbstractEntityInitializer extends AbstractFetchParentAcces
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected Object[] extractConcreteTypeStateValues(RowProcessingState rowProcessingState) {
|
protected Object[] extractConcreteTypeStateValues(RowProcessingState rowProcessingState) {
|
||||||
final Object[] values = new Object[concreteDescriptor.getNumberOfAttributeMappings()];
|
final Object[] values = new Object[concreteDescriptor.getNumberOfAttributeMappings()];
|
||||||
|
|
|
@ -60,6 +60,7 @@ import org.hibernate.metamodel.model.domain.NavigableRole;
|
||||||
import org.hibernate.metamodel.spi.EntityRepresentationStrategy;
|
import org.hibernate.metamodel.spi.EntityRepresentationStrategy;
|
||||||
import org.hibernate.persister.collection.CollectionPersister;
|
import org.hibernate.persister.collection.CollectionPersister;
|
||||||
import org.hibernate.persister.entity.EntityPersister;
|
import org.hibernate.persister.entity.EntityPersister;
|
||||||
|
import org.hibernate.persister.entity.UniqueKeyEntry;
|
||||||
import org.hibernate.persister.spi.PersisterClassResolver;
|
import org.hibernate.persister.spi.PersisterClassResolver;
|
||||||
import org.hibernate.persister.spi.PersisterCreationContext;
|
import org.hibernate.persister.spi.PersisterCreationContext;
|
||||||
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableInsertStrategy;
|
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableInsertStrategy;
|
||||||
|
@ -753,6 +754,11 @@ public class GoofyPersisterClassProvider implements PersisterClassResolver {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterable<UniqueKeyEntry> uniqueKeyEntries() {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isAffectedByEnabledFilters(LoadQueryInfluencers influencers) {
|
public boolean isAffectedByEnabledFilters(LoadQueryInfluencers influencers) {
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -58,6 +58,7 @@ import org.hibernate.metamodel.spi.EntityRepresentationStrategy;
|
||||||
import org.hibernate.orm.test.jpa.SettingsGenerator;
|
import org.hibernate.orm.test.jpa.SettingsGenerator;
|
||||||
import org.hibernate.persister.collection.CollectionPersister;
|
import org.hibernate.persister.collection.CollectionPersister;
|
||||||
import org.hibernate.persister.entity.EntityPersister;
|
import org.hibernate.persister.entity.EntityPersister;
|
||||||
|
import org.hibernate.persister.entity.UniqueKeyEntry;
|
||||||
import org.hibernate.persister.internal.PersisterClassResolverInitiator;
|
import org.hibernate.persister.internal.PersisterClassResolverInitiator;
|
||||||
import org.hibernate.persister.spi.PersisterClassResolver;
|
import org.hibernate.persister.spi.PersisterClassResolver;
|
||||||
import org.hibernate.persister.spi.PersisterCreationContext;
|
import org.hibernate.persister.spi.PersisterCreationContext;
|
||||||
|
@ -722,6 +723,11 @@ public class PersisterClassProviderTest {
|
||||||
return false; //To change body of implemented methods use File | Settings | File Templates.
|
return false; //To change body of implemented methods use File | Settings | File Templates.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterable<UniqueKeyEntry> uniqueKeyEntries() {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CacheEntry buildCacheEntry(Object entity, Object[] state, Object version, SharedSessionContractImplementor session) {
|
public CacheEntry buildCacheEntry(Object entity, Object[] state, Object version, SharedSessionContractImplementor session) {
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -57,6 +57,7 @@ import org.hibernate.metamodel.mapping.TableDetails;
|
||||||
import org.hibernate.metamodel.model.domain.NavigableRole;
|
import org.hibernate.metamodel.model.domain.NavigableRole;
|
||||||
import org.hibernate.metamodel.spi.EntityRepresentationStrategy;
|
import org.hibernate.metamodel.spi.EntityRepresentationStrategy;
|
||||||
import org.hibernate.persister.entity.EntityPersister;
|
import org.hibernate.persister.entity.EntityPersister;
|
||||||
|
import org.hibernate.persister.entity.UniqueKeyEntry;
|
||||||
import org.hibernate.persister.spi.PersisterCreationContext;
|
import org.hibernate.persister.spi.PersisterCreationContext;
|
||||||
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableInsertStrategy;
|
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableInsertStrategy;
|
||||||
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy;
|
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy;
|
||||||
|
@ -845,6 +846,11 @@ public class CustomPersister implements EntityPersister {
|
||||||
return false; //To change body of implemented methods use File | Settings | File Templates.
|
return false; //To change body of implemented methods use File | Settings | File Templates.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterable<UniqueKeyEntry> uniqueKeyEntries() {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isAffectedByEntityGraph(LoadQueryInfluencers loadQueryInfluencers) {
|
public boolean isAffectedByEntityGraph(LoadQueryInfluencers loadQueryInfluencers) {
|
||||||
return loadQueryInfluencers.getEffectiveEntityGraph().getGraph() != null;
|
return loadQueryInfluencers.getEffectiveEntityGraph().getGraph() != null;
|
||||||
|
|
Loading…
Reference in New Issue