Skip to content

Commit 9a6fc44

Browse files
committed
refactor ResultsHelper (extract some methods)
1 parent 5b205d5 commit 9a6fc44

File tree

1 file changed

+132
-98
lines changed

1 file changed

+132
-98
lines changed

hibernate-core/src/main/java/org/hibernate/sql/results/internal/ResultsHelper.java

Lines changed: 132 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -6,30 +6,21 @@
66

77

88
import org.hibernate.CacheMode;
9-
import org.hibernate.cache.spi.access.CollectionDataAccess;
9+
import org.hibernate.SharedSessionContract;
1010
import org.hibernate.cache.spi.entry.CollectionCacheEntry;
1111
import org.hibernate.collection.spi.PersistentCollection;
12-
import org.hibernate.engine.spi.BatchFetchQueue;
1312
import org.hibernate.engine.spi.CollectionEntry;
14-
import org.hibernate.engine.spi.EntityEntry;
1513
import org.hibernate.engine.spi.PersistenceContext;
16-
import org.hibernate.engine.spi.SessionEventListenerManager;
1714
import org.hibernate.engine.spi.SessionFactoryImplementor;
1815
import org.hibernate.engine.spi.SharedSessionContractImplementor;
1916
import org.hibernate.event.monitor.spi.EventMonitor;
20-
import org.hibernate.event.monitor.spi.DiagnosticEvent;
2117
import org.hibernate.internal.CoreLogging;
2218
import org.hibernate.internal.CoreMessageLogger;
23-
import org.hibernate.metamodel.mapping.PluralAttributeMapping;
2419
import org.hibernate.persister.collection.CollectionPersister;
25-
import org.hibernate.persister.entity.EntityPersister;
2620
import org.hibernate.sql.results.jdbc.spi.JdbcValues;
2721
import org.hibernate.sql.results.jdbc.spi.JdbcValuesMapping;
28-
import org.hibernate.sql.results.jdbc.spi.JdbcValuesMappingResolution;
2922
import org.hibernate.sql.results.spi.RowReader;
3023
import org.hibernate.sql.results.spi.RowTransformer;
31-
import org.hibernate.stat.spi.StatisticsImplementor;
32-
import org.hibernate.type.EntityType;
3324

3425
import static org.hibernate.pretty.MessageHelper.collectionInfoString;
3526

@@ -53,9 +44,8 @@ public static <R> RowReader<R> createRowReader(
5344
RowTransformer<R> rowTransformer,
5445
Class<R> transformedResultJavaType,
5546
JdbcValuesMapping jdbcValuesMapping) {
56-
final JdbcValuesMappingResolution jdbcValuesMappingResolution = jdbcValuesMapping.resolveAssemblers( sessionFactory );
5747
return new StandardRowReader<>(
58-
jdbcValuesMappingResolution,
48+
jdbcValuesMapping.resolveAssemblers( sessionFactory ),
5949
rowTransformer,
6050
transformedResultJavaType
6151
);
@@ -64,81 +54,95 @@ public static <R> RowReader<R> createRowReader(
6454
public static void finalizeCollectionLoading(
6555
PersistenceContext persistenceContext,
6656
CollectionPersister collectionDescriptor,
67-
PersistentCollection<?> collectionInstance,
57+
PersistentCollection<?> collection,
6858
Object key,
6959
boolean hasNoQueuedAdds) {
70-
final SharedSessionContractImplementor session = persistenceContext.getSession();
71-
72-
CollectionEntry collectionEntry = persistenceContext.getCollectionEntry( collectionInstance );
73-
if ( collectionEntry == null ) {
74-
collectionEntry = persistenceContext.addInitializedCollection( collectionDescriptor, collectionInstance, key );
75-
}
76-
else {
77-
collectionEntry.postInitialize( collectionInstance, session );
78-
}
79-
60+
final var session = persistenceContext.getSession();
61+
final var collectionEntry =
62+
initializedEntry( persistenceContext, collectionDescriptor, collection, key, session );
8063
if ( collectionDescriptor.getCollectionType().hasHolder() ) {
81-
// in case of PersistentArrayHolder we have to realign
82-
// the EntityEntry loaded state with the entity values
83-
final Object owner = collectionInstance.getOwner();
84-
final EntityEntry entry = persistenceContext.getEntry( owner );
85-
final Object[] loadedState = entry.getLoadedState();
86-
if ( loadedState != null ) {
87-
final PluralAttributeMapping mapping = collectionDescriptor.getAttributeMapping();
88-
final int propertyIndex = mapping.getStateArrayPosition();
89-
loadedState[propertyIndex] = mapping.getValue( owner );
90-
}
91-
// else it must be an immutable entity or loaded in read-only mode,
92-
// but unfortunately we have no way to reliably determine that here
93-
persistenceContext.addCollectionHolder( collectionInstance );
64+
addCollectionHolder( persistenceContext, collectionDescriptor, collection );
9465
}
95-
96-
final BatchFetchQueue batchFetchQueue = persistenceContext.getBatchFetchQueue();
97-
batchFetchQueue.removeBatchLoadableCollection( collectionEntry );
98-
99-
// add to cache if:
100-
final boolean addToCache =
101-
// there were no queued additions
102-
hasNoQueuedAdds
103-
// and the role has a cache
104-
&& collectionDescriptor.hasCache()
105-
// and this is not a forced initialization during flush
106-
&& session.getCacheMode().isPutEnabled() && !collectionEntry.isDoremove();
107-
if ( addToCache ) {
108-
addCollectionToCache( persistenceContext, collectionDescriptor, collectionInstance, key );
66+
persistenceContext.getBatchFetchQueue().removeBatchLoadableCollection( collectionEntry );
67+
if ( addToCache( session, collectionEntry, collectionDescriptor, hasNoQueuedAdds ) ) {
68+
addCollectionToCache( persistenceContext, collectionDescriptor, collection, key );
69+
}
70+
final var statistics = session.getFactory().getStatistics();
71+
if ( statistics.isStatisticsEnabled() ) {
72+
statistics.loadCollection( collectionDescriptor.getRole() );
10973
}
11074

11175
if ( LOG.isTraceEnabled() ) {
11276
LOG.trace( "Collection fully initialized: "
113-
+ collectionInfoString( collectionDescriptor, collectionInstance, key, session ) );
114-
}
115-
116-
final StatisticsImplementor statistics = session.getFactory().getStatistics();
117-
if ( statistics.isStatisticsEnabled() ) {
118-
statistics.loadCollection( collectionDescriptor.getRole() );
77+
+ collectionInfoString( collectionDescriptor, collection, key, session ) );
11978
}
12079

12180
// todo (6.0) : there is other logic still needing to be implemented here. caching, etc
12281
// see org.hibernate.engine.loading.internal.CollectionLoadContext#endLoadingCollection in 5.x
12382
}
12483

84+
private static boolean addToCache(
85+
SharedSessionContract session,
86+
CollectionEntry collectionEntry,
87+
CollectionPersister collectionDescriptor,
88+
boolean hasNoQueuedAdds) {
89+
return hasNoQueuedAdds // there were no queued additions
90+
&& collectionDescriptor.hasCache() // the collection role has a cache
91+
&& session.getCacheMode().isPutEnabled() // the session cache mode allows puts
92+
&& !collectionEntry.isDoremove(); // this is not a forced initialization during flush
93+
}
94+
95+
private static void addCollectionHolder(
96+
PersistenceContext persistenceContext,
97+
CollectionPersister collectionDescriptor,
98+
PersistentCollection<?> collectionInstance) {
99+
// in case of PersistentArrayHolder we have to realign
100+
// the EntityEntry loaded state with the entity values
101+
final Object owner = collectionInstance.getOwner();
102+
final var loadedState = persistenceContext.getEntry( owner ).getLoadedState();
103+
if ( loadedState != null ) {
104+
final var mapping = collectionDescriptor.getAttributeMapping();
105+
final int propertyIndex = mapping.getStateArrayPosition();
106+
loadedState[propertyIndex] = mapping.getValue( owner );
107+
}
108+
// else it must be an immutable entity or loaded in read-only mode,
109+
// but, unfortunately, we have no way to reliably determine that here
110+
persistenceContext.addCollectionHolder( collectionInstance );
111+
}
112+
113+
private static CollectionEntry initializedEntry(
114+
PersistenceContext context,
115+
CollectionPersister collectionDescriptor,
116+
PersistentCollection<?> collectionInstance,
117+
Object key,
118+
SharedSessionContractImplementor session) {
119+
final var collectionEntry = context.getCollectionEntry( collectionInstance );
120+
if ( collectionEntry == null ) {
121+
return context.addInitializedCollection( collectionDescriptor, collectionInstance, key );
122+
}
123+
else {
124+
collectionEntry.postInitialize( collectionInstance, session );
125+
return collectionEntry;
126+
}
127+
}
128+
125129
/**
126130
* Add the collection to the second-level cache
127131
*/
128132
private static void addCollectionToCache(
129133
PersistenceContext persistenceContext,
130134
CollectionPersister collectionDescriptor,
131-
PersistentCollection<?> collectionInstance,
135+
PersistentCollection<?> collection,
132136
Object key) {
133-
final SharedSessionContractImplementor session = persistenceContext.getSession();
134-
final SessionFactoryImplementor factory = session.getFactory();
137+
final var session = persistenceContext.getSession();
135138

136139
if ( LOG.isTraceEnabled() ) {
137140
LOG.trace( "Caching collection: "
138-
+ collectionInfoString( collectionDescriptor, collectionInstance, key, session ) );
141+
+ collectionInfoString( collectionDescriptor, collection, key, session ) );
139142
}
140143

141-
if ( session.getLoadQueryInfluencers().hasEnabledFilters() && collectionDescriptor.isAffectedByEnabledFilters( session ) ) {
144+
if ( session.getLoadQueryInfluencers().hasEnabledFilters()
145+
&& collectionDescriptor.isAffectedByEnabledFilters( session ) ) {
142146
// some filters affecting the collection are enabled on the session, so do not do the put into the cache.
143147
LOG.debug( "Refusing to add to cache due to enabled filters" );
144148
// todo : add the notion of enabled filters to the cache key to differentiate filtered collections from non-filtered;
@@ -150,56 +154,43 @@ private static void addCollectionToCache(
150154

151155
final Object version;
152156
if ( collectionDescriptor.isVersioned() ) {
153-
Object collectionOwner = persistenceContext.getCollectionOwner( key, collectionDescriptor );
157+
final Object collectionOwner =
158+
getCollectionOwner( persistenceContext, collectionDescriptor, collection, key, session );
154159
if ( collectionOwner == null ) {
155-
// generally speaking this would be caused by the collection key being defined by a property-ref, thus
156-
// the collection key and the owner key would not match up. In this case, try to use the key of the
157-
// owner instance associated with the collection itself, if one. If the collection does already know
158-
// about its owner, that owner should be the same instance as associated with the PC, but we do the
159-
// resolution against the PC anyway just to be safe since the lookup should not be costly.
160-
if ( collectionInstance != null ) {
161-
final Object linkedOwner = collectionInstance.getOwner();
162-
if ( linkedOwner != null ) {
163-
final Object ownerKey = collectionDescriptor.getOwnerEntityPersister().getIdentifier( linkedOwner, session );
164-
collectionOwner = persistenceContext.getCollectionOwner( ownerKey, collectionDescriptor );
165-
}
166-
}
167-
if ( collectionOwner == null ) {
168-
LOG.debugf( "Unable to resolve owner of loading collection for second level caching. Refusing to add to cache.");
169-
return;
170-
}
160+
LOG.debug( "Unable to resolve owner of loading collection for second level caching. Refusing to add to cache.");
161+
return;
171162
}
172163
version = persistenceContext.getEntry( collectionOwner ).getVersion();
173164
}
174165
else {
175166
version = null;
176167
}
177168

178-
final CollectionCacheEntry entry = new CollectionCacheEntry( collectionInstance, collectionDescriptor );
179-
final CollectionDataAccess cacheAccess = collectionDescriptor.getCacheAccessStrategy();
169+
addCollectionToCache( persistenceContext, collectionDescriptor, collection, key, version );
170+
}
171+
172+
private static void addCollectionToCache(
173+
PersistenceContext context,
174+
CollectionPersister collectionDescriptor,
175+
PersistentCollection<?> collection,
176+
Object key,
177+
Object version) {
178+
final var session = context.getSession();
179+
final var factory = session.getFactory();
180+
final var entry = new CollectionCacheEntry( collection, collectionDescriptor );
181+
final var cacheAccess = collectionDescriptor.getCacheAccessStrategy();
180182
final Object cacheKey = cacheAccess.generateCacheKey(
181183
key,
182184
collectionDescriptor,
183185
session.getFactory(),
184186
session.getTenantIdentifier()
185187
);
186188

187-
boolean isPutFromLoad = true;
188-
if ( collectionDescriptor.getElementType() instanceof EntityType ) {
189-
final EntityPersister entityPersister = collectionDescriptor.getElementPersister();
190-
for ( Object id : entry.getState() ) {
191-
if ( persistenceContext.wasInsertedDuringTransaction( entityPersister, id ) ) {
192-
isPutFromLoad = false;
193-
break;
194-
}
195-
}
196-
}
197-
198189
// CollectionRegionAccessStrategy has no update, so avoid putting uncommitted data via putFromLoad
199-
if ( isPutFromLoad ) {
200-
final SessionEventListenerManager eventListenerManager = session.getEventListenerManager();
201-
final EventMonitor eventMonitor = session.getEventMonitor();
202-
final DiagnosticEvent cachePutEvent = eventMonitor.beginCachePutEvent();
190+
if ( isPutFromLoad( context, collectionDescriptor, entry ) ) {
191+
final var eventListenerManager = session.getEventListenerManager();
192+
final var eventMonitor = session.getEventMonitor();
193+
final var cachePutEvent = eventMonitor.beginCachePutEvent();
203194
boolean put = false;
204195
try {
205196
eventListenerManager.cachePutStart();
@@ -209,7 +200,7 @@ private static void addCollectionToCache(
209200
collectionDescriptor.getCacheEntryStructure().structure( entry ),
210201
version,
211202
factory.getSessionFactoryOptions().isMinimalPutsEnabled()
212-
&& session.getCacheMode()!= CacheMode.REFRESH
203+
&& session.getCacheMode() != CacheMode.REFRESH
213204
);
214205
}
215206
finally {
@@ -223,15 +214,58 @@ private static void addCollectionToCache(
223214
);
224215
eventListenerManager.cachePutEnd();
225216

226-
final StatisticsImplementor statistics = factory.getStatistics();
217+
final var statistics = factory.getStatistics();
227218
if ( put && statistics.isStatisticsEnabled() ) {
228219
statistics.collectionCachePut(
229220
collectionDescriptor.getNavigableRole(),
230-
collectionDescriptor.getCacheAccessStrategy().getRegion().getName()
221+
cacheAccess.getRegion().getName()
231222
);
232223
}
224+
}
225+
}
226+
}
227+
228+
private static boolean isPutFromLoad(
229+
PersistenceContext context,
230+
CollectionPersister collectionDescriptor,
231+
CollectionCacheEntry entry) {
232+
if ( collectionDescriptor.getElementType().isEntityType() ) {
233+
final var entityPersister = collectionDescriptor.getElementPersister();
234+
for ( Object id : entry.getState() ) {
235+
if ( context.wasInsertedDuringTransaction( entityPersister, id ) ) {
236+
return false;
237+
}
238+
}
239+
}
240+
return true;
241+
}
233242

243+
private static Object getCollectionOwner(
244+
PersistenceContext context,
245+
CollectionPersister collectionDescriptor,
246+
PersistentCollection<?> collection,
247+
Object key,
248+
SharedSessionContractImplementor session) {
249+
final Object collectionOwner = context.getCollectionOwner( key, collectionDescriptor );
250+
if ( collectionOwner == null ) {
251+
// This happens when the collection key is defined by a property-ref. In this case, the collection key
252+
// and the owner key would not match up. Use the key of the owner instance associated with the collection
253+
// itself, if there is one. If the collection does already know about its owner, that owner should be the
254+
// same instance as associated with the PC, but we do the resolution against the PC anyway just to be safe,
255+
// since the lookup should not be costly.
256+
if ( collection != null ) {
257+
final Object linkedOwner = collection.getOwner();
258+
if ( linkedOwner != null ) {
259+
final Object ownerKey =
260+
collectionDescriptor.getOwnerEntityPersister()
261+
.getIdentifier( linkedOwner, session );
262+
return context.getCollectionOwner( ownerKey, collectionDescriptor );
263+
}
234264
}
265+
return null;
266+
}
267+
else {
268+
return collectionOwner;
235269
}
236270
}
237271
}

0 commit comments

Comments
 (0)