Skip to content

Commit 2b92c3d

Browse files
Sannebeikov
authored andcommitted
HHH-16728 Optimise iteration of AssociationType properties within a Persister
1 parent 0d58a24 commit 2b92c3d

File tree

7 files changed

+115
-26
lines changed

7 files changed

+115
-26
lines changed

hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java

+28
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@
120120
import org.hibernate.internal.util.LazyValue;
121121
import org.hibernate.internal.util.StringHelper;
122122
import org.hibernate.internal.util.collections.ArrayHelper;
123+
import org.hibernate.internal.util.collections.CollectionHelper;
123124
import org.hibernate.internal.util.collections.LockModeEnumMap;
124125
import org.hibernate.jdbc.Expectation;
125126
import org.hibernate.jdbc.TooManyRowsAffectedException;
@@ -279,6 +280,7 @@
279280
import org.hibernate.tuple.NonIdentifierAttribute;
280281
import org.hibernate.tuple.entity.EntityMetamodel;
281282
import org.hibernate.type.AnyType;
283+
import org.hibernate.type.AssociationType;
282284
import org.hibernate.type.BasicType;
283285
import org.hibernate.type.CollectionType;
284286
import org.hibernate.type.CompositeType;
@@ -464,6 +466,8 @@ public abstract class AbstractEntityPersister
464466

465467
private final boolean implementsLifecycle;
466468

469+
private List<UniqueKeyEntry> uniqueKeyEntries = null; //lazily initialized
470+
467471
@Deprecated(since = "6.0")
468472
public AbstractEntityPersister(
469473
final PersistentClass persistentClass,
@@ -1166,6 +1170,30 @@ public boolean canUseReferenceCacheEntries() {
11661170
return useReferenceCacheEntries;
11671171
}
11681172

1173+
@Override
1174+
public Iterable<UniqueKeyEntry> uniqueKeyEntries() {
1175+
if ( this.uniqueKeyEntries == null ) {
1176+
this.uniqueKeyEntries = initUniqueKeyEntries( this );
1177+
}
1178+
return this.uniqueKeyEntries;
1179+
}
1180+
1181+
private static List<UniqueKeyEntry> initUniqueKeyEntries(final AbstractEntityPersister aep) {
1182+
ArrayList<UniqueKeyEntry> uniqueKeys = new ArrayList();
1183+
for ( Type propertyType : aep.getPropertyTypes() ) {
1184+
if ( propertyType instanceof AssociationType ) {
1185+
final AssociationType associationType = (AssociationType) propertyType;
1186+
final String ukName = associationType.getLHSPropertyName();
1187+
if ( ukName != null ) {
1188+
final int index = aep.findAttributeMapping( ukName ).getStateArrayPosition();
1189+
final Type type = aep.getPropertyTypes()[index];
1190+
uniqueKeys.add( new UniqueKeyEntry( ukName, index, type ) );
1191+
}
1192+
}
1193+
}
1194+
return CollectionHelper.toSmallList( uniqueKeys );
1195+
}
1196+
11691197
protected Map<String, SingleIdArrayLoadPlan> getLazyLoadPlanByFetchGroup() {
11701198
final BytecodeEnhancementMetadata metadata = entityMetamodel.getBytecodeEnhancementMetadata();
11711199
return metadata.isEnhancedForLazyLoading() && metadata.getLazyAttributesMetadata().hasLazyAttributes()

hibernate-core/src/main/java/org/hibernate/persister/entity/EntityPersister.java

+7
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import java.util.function.Consumer;
1313

1414
import org.hibernate.HibernateException;
15+
import org.hibernate.Incubating;
1516
import org.hibernate.LockMode;
1617
import org.hibernate.LockOptions;
1718
import org.hibernate.MappingException;
@@ -1075,4 +1076,10 @@ default int[] resolveDirtyAttributeIndexes(
10751076
@Deprecated(since = "6.2")
10761077
String ENTITY_ID = "id";
10771078

1079+
/**
1080+
* @return Metadata for each unique key defined
1081+
*/
1082+
@Incubating
1083+
Iterable<UniqueKeyEntry> uniqueKeyEntries();
1084+
10781085
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/*
2+
* Hibernate, Relational Persistence for Idiomatic Java
3+
*
4+
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
5+
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
6+
*/
7+
package org.hibernate.persister.entity;
8+
9+
import java.util.Objects;
10+
11+
import org.hibernate.type.Type;
12+
13+
/**
14+
* Useful metadata representing a unique key within a Persister
15+
*/
16+
public final class UniqueKeyEntry {
17+
18+
private final String uniqueKeyName;
19+
private final int stateArrayPosition;
20+
private final Type propertyType;
21+
22+
public UniqueKeyEntry(final String uniqueKeyName, final int stateArrayPosition, final Type propertyType) {
23+
this.uniqueKeyName = Objects.requireNonNull( uniqueKeyName );
24+
this.stateArrayPosition = stateArrayPosition;
25+
this.propertyType = Objects.requireNonNull( propertyType );
26+
}
27+
28+
public String getUniqueKeyName() {
29+
return this.uniqueKeyName;
30+
}
31+
32+
public int getStateArrayPosition() {
33+
return this.stateArrayPosition;
34+
}
35+
36+
public Type getPropertyType() {
37+
return this.propertyType;
38+
}
39+
40+
}

hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/AbstractEntityInitializer.java

+22-26
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
import org.hibernate.metamodel.mapping.ManagedMappingType;
4242
import org.hibernate.metamodel.mapping.ModelPart;
4343
import org.hibernate.persister.entity.EntityPersister;
44+
import org.hibernate.persister.entity.UniqueKeyEntry;
4445
import org.hibernate.property.access.internal.PropertyAccessStrategyBackRefImpl;
4546
import org.hibernate.proxy.LazyInitializer;
4647
import org.hibernate.proxy.map.MapProxy;
@@ -1034,32 +1035,27 @@ private void putInCache(
10341035
}
10351036
}
10361037

1037-
protected void registerPossibleUniqueKeyEntries(Object toInitialize, SharedSessionContractImplementor session) {
1038-
for ( Type propertyType : concreteDescriptor.getPropertyTypes() ) {
1039-
if ( propertyType instanceof AssociationType ) {
1040-
final AssociationType associationType = (AssociationType) propertyType;
1041-
final String ukName = associationType.getLHSPropertyName();
1042-
if ( ukName != null ) {
1043-
final int index = concreteDescriptor.findAttributeMapping( ukName ).getStateArrayPosition();
1044-
final Type type = concreteDescriptor.getPropertyTypes()[index];
1045-
1046-
// polymorphism not really handled completely correctly,
1047-
// perhaps...well, actually its ok, assuming that the
1048-
// entity name used in the lookup is the same as the
1049-
// one used here, which it will be
1050-
1051-
if ( resolvedEntityState[index] != null ) {
1052-
final EntityUniqueKey euk = new EntityUniqueKey(
1053-
concreteDescriptor.getRootEntityDescriptor().getEntityName(),
1054-
//polymorphism comment above
1055-
ukName,
1056-
resolvedEntityState[index],
1057-
type,
1058-
session.getFactory()
1059-
);
1060-
session.getPersistenceContextInternal().addEntity( euk, toInitialize );
1061-
}
1062-
}
1038+
protected void registerPossibleUniqueKeyEntries(final Object toInitialize, final SharedSessionContractImplementor session) {
1039+
for ( UniqueKeyEntry entry : concreteDescriptor.uniqueKeyEntries() ) {
1040+
final String ukName = entry.getUniqueKeyName();
1041+
final int index = entry.getStateArrayPosition();//concreteDescriptor.findAttributeMapping( ukName ).getStateArrayPosition();
1042+
final Type type = entry.getPropertyType();//concreteDescriptor.getPropertyTypes()[index];
1043+
1044+
// polymorphism not really handled completely correctly,
1045+
// perhaps...well, actually its ok, assuming that the
1046+
// entity name used in the lookup is the same as the
1047+
// one used here, which it will be
1048+
1049+
if ( resolvedEntityState[index] != null ) {
1050+
final EntityUniqueKey euk = new EntityUniqueKey(
1051+
concreteDescriptor.getRootEntityDescriptor().getEntityName(),
1052+
//polymorphism comment above
1053+
ukName,
1054+
resolvedEntityState[index],
1055+
type,
1056+
session.getFactory()
1057+
);
1058+
session.getPersistenceContextInternal().addEntity( euk, toInitialize );
10631059
}
10641060
}
10651061
}

hibernate-core/src/test/java/org/hibernate/orm/test/cfg/persister/GoofyPersisterClassProvider.java

+6
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@
6060
import org.hibernate.metamodel.spi.EntityRepresentationStrategy;
6161
import org.hibernate.persister.collection.CollectionPersister;
6262
import org.hibernate.persister.entity.EntityPersister;
63+
import org.hibernate.persister.entity.UniqueKeyEntry;
6364
import org.hibernate.persister.spi.PersisterClassResolver;
6465
import org.hibernate.persister.spi.PersisterCreationContext;
6566
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableInsertStrategy;
@@ -758,6 +759,11 @@ public boolean canUseReferenceCacheEntries() {
758759
return false;
759760
}
760761

762+
@Override
763+
public Iterable<UniqueKeyEntry> uniqueKeyEntries() {
764+
return Collections.emptyList();
765+
}
766+
761767
@Override
762768
public boolean isAffectedByEnabledFilters(LoadQueryInfluencers influencers) {
763769
return false;

hibernate-core/src/test/java/org/hibernate/orm/test/jpa/ejb3configuration/PersisterClassProviderTest.java

+6
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@
5858
import org.hibernate.orm.test.jpa.SettingsGenerator;
5959
import org.hibernate.persister.collection.CollectionPersister;
6060
import org.hibernate.persister.entity.EntityPersister;
61+
import org.hibernate.persister.entity.UniqueKeyEntry;
6162
import org.hibernate.persister.internal.PersisterClassResolverInitiator;
6263
import org.hibernate.persister.spi.PersisterClassResolver;
6364
import org.hibernate.persister.spi.PersisterCreationContext;
@@ -729,6 +730,11 @@ public boolean canUseReferenceCacheEntries() {
729730
return false; //To change body of implemented methods use File | Settings | File Templates.
730731
}
731732

733+
@Override
734+
public Iterable<UniqueKeyEntry> uniqueKeyEntries() {
735+
return Collections.emptyList();
736+
}
737+
732738
@Override
733739
public CacheEntry buildCacheEntry(Object entity, Object[] state, Object version, SharedSessionContractImplementor session) {
734740
return null;

hibernate-core/src/test/java/org/hibernate/orm/test/legacy/CustomPersister.java

+6
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@
5757
import org.hibernate.metamodel.model.domain.NavigableRole;
5858
import org.hibernate.metamodel.spi.EntityRepresentationStrategy;
5959
import org.hibernate.persister.entity.EntityPersister;
60+
import org.hibernate.persister.entity.UniqueKeyEntry;
6061
import org.hibernate.persister.spi.PersisterCreationContext;
6162
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableInsertStrategy;
6263
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy;
@@ -849,6 +850,11 @@ public boolean canUseReferenceCacheEntries() {
849850
return false; //To change body of implemented methods use File | Settings | File Templates.
850851
}
851852

853+
@Override
854+
public Iterable<UniqueKeyEntry> uniqueKeyEntries() {
855+
return Collections.emptyList();
856+
}
857+
852858
@Override
853859
public boolean isAffectedByEntityGraph(LoadQueryInfluencers loadQueryInfluencers) {
854860
return loadQueryInfluencers.getEffectiveEntityGraph().getGraph() != null;

0 commit comments

Comments
 (0)