1818import  org .hibernate .type .CompositeType ;
1919import  org .hibernate .type .Type ;
2020
21+ import  static  java .util .Collections .unmodifiableSet ;
2122import  static  org .hibernate .engine .internal .ManagedTypeHelper .asPersistentAttributeInterceptable ;
2223import  static  org .hibernate .engine .internal .ManagedTypeHelper .asSelfDirtinessTracker ;
2324import  static  org .hibernate .engine .internal .ManagedTypeHelper .isSelfDirtinessTrackerType ;
25+ import  static  org .hibernate .internal .util .collections .CollectionHelper .toSmallSet ;
2426
2527/** 
2628 * @author Steve Ebersole 
2729 */ 
2830public  class  EnhancementAsProxyLazinessInterceptor  extends  AbstractInterceptor  implements  BytecodeLazyAttributeInterceptor  {
29- 	private  final  Set <String > identifierAttributeNames ;
30- 	private  final  CompositeType  nonAggregatedCidMapper ;
31- 	private  final  String  entityName ;
3231
3332	private  final  EntityKey  entityKey ;
34- 
35- 	private  final  boolean  inLineDirtyChecking ;
33+ 	private  final  EntityRelatedState  meta ;
3634	private  Set <String > writtenFieldNames ;
37- 	private  Set <String > collectionAttributeNames ;
38- 
3935	private  Status  status ;
4036
41- 	private  final  boolean  initializeBeforeWrite ;
42- 
4337	public  EnhancementAsProxyLazinessInterceptor (
44- 			String  entityName ,
45- 			Set <String > identifierAttributeNames ,
46- 			CompositeType  nonAggregatedCidMapper ,
38+ 			EntityRelatedState  meta ,
4739			EntityKey  entityKey ,
4840			SharedSessionContractImplementor  session ) {
49- 		this .entityName  = entityName ;
50- 
51- 		this .identifierAttributeNames  = identifierAttributeNames ;
52- 		assert  identifierAttributeNames  != null ;
53- 
54- 		this .nonAggregatedCidMapper  = nonAggregatedCidMapper ;
55- 		assert  nonAggregatedCidMapper  != null  || identifierAttributeNames .size () == 1 ;
56- 
5741		this .entityKey  = entityKey ;
58- 		setSession ( session  );
59- 
60- 		final  EntityPersister  entityPersister  =
61- 				session .getFactory ().getMappingMetamodel ()
62- 						.getEntityDescriptor ( entityName  );
63- 		if  ( entityPersister .hasCollections () ) {
64- 			final  Type [] propertyTypes  = entityPersister .getPropertyTypes ();
65- 			final  String [] propertyNames  = entityPersister .getPropertyNames ();
66- 			collectionAttributeNames  = new  HashSet <>();
67- 			for  ( int  i  = 0 ; i  < propertyTypes .length ; i ++ ) {
68- 				Type  propertyType  = propertyTypes [i ];
69- 				if  ( propertyType  instanceof  CollectionType  ) {
70- 					collectionAttributeNames .add ( propertyNames [i ] );
71- 				}
72- 			}
73- 		}
74- 
75- 		this .inLineDirtyChecking  = isSelfDirtinessTrackerType ( entityPersister .getMappedClass () );
76- 		// if self-dirty tracking is enabled but DynamicUpdate is not enabled then we need to 
77- 		// initialize the entity because the precomputed update statement contains even not 
78- 		// dirty properties. And so we need all the values we have to initialize. Or, if it's 
79- 		// versioned, we need to fetch the current version. 
80- 		initializeBeforeWrite  =
81- 				!inLineDirtyChecking 
82- 						|| !entityPersister .getEntityMetamodel ().isDynamicUpdate ()
83- 						|| entityPersister .isVersioned ();
42+ 		this .meta  = meta ;
8443		status  = Status .UNINITIALIZED ;
44+ 		setSession ( session  );
8545	}
8646
8747	@ Override 
8848	public  String  getEntityName () {
89- 		return  entityName ;
49+ 		return  meta . entityName ;
9050	}
9151
9252	public  EntityKey  getEntityKey () {
@@ -102,7 +62,7 @@ protected Object handleRead(Object target, String attributeName, Object value) {
10262
10363		// the attribute being read is an entity-id attribute 
10464		// 		- we already know the id, return that 
105- 		if  ( identifierAttributeNames .contains ( attributeName  ) ) {
65+ 		if  ( meta . identifierAttributeNames .contains ( attributeName  ) ) {
10666			return  extractIdValue ( target , attributeName  );
10767		}
10868
@@ -120,14 +80,10 @@ private Object read(
12080		final  Object [] writtenAttributeValues ;
12181		final  AttributeMapping [] writtenAttributeMappings ;
12282
123- 		final  EntityPersister  entityPersister  =
124- 				session .getFactory ().getMappingMetamodel ()
125- 						.getEntityDescriptor ( getEntityName () );
126- 
12783		if  ( writtenFieldNames  != null  && !writtenFieldNames .isEmpty () ) {
12884
12985			// enhancement has dirty-tracking available and at least one attribute was explicitly set 
130- 
86+ 			 final   EntityPersister   entityPersister  =  meta . persister ; 
13187			if  ( writtenFieldNames .contains ( attributeName  ) ) {
13288				// the requested attribute was one of the attributes explicitly set, 
13389				// we can just return the explicitly-set value 
@@ -162,7 +118,7 @@ private Object read(
162118			for  ( int  i  = 0 ; i  < writtenAttributeMappings .length ; i ++ ) {
163119				final  AttributeMapping  attribute  = writtenAttributeMappings [i ];
164120				attribute .setValue (target , writtenAttributeValues [i ] );
165- 				if  ( inLineDirtyChecking  ) {
121+ 				if  ( meta . inLineDirtyChecking  ) {
166122					asSelfDirtinessTracker (target ).$$_hibernate_trackChange ( attribute .getAttributeName () );
167123				}
168124			}
@@ -174,6 +130,7 @@ private Object read(
174130
175131	private  Object  extractIdValue (Object  target , String  attributeName ) {
176132		// access to the id or part of it for non-aggregated cid 
133+ 		final  CompositeType  nonAggregatedCidMapper  = meta .nonAggregatedCidMapper ;
177134		if  ( nonAggregatedCidMapper  == null  ) {
178135			return  getIdentifier ();
179136		}
@@ -218,17 +175,13 @@ public Object forceInitialize(
218175			);
219176		}
220177
221- 		final  EntityPersister  persister  =
222- 				session .getFactory ().getMappingMetamodel ()
223- 						.getEntityDescriptor ( getEntityName () );
224- 
225178		if  ( isTemporarySession  ) {
226179			// Add an entry for this entity in the PC of the temp Session 
227180			session .getPersistenceContext ()
228181					.addEnhancedProxy ( entityKey , asPersistentAttributeInterceptable ( target  ) );
229182		}
230183
231- 		return  persister .initializeEnhancedEntityUsedAsProxy ( target , attributeName , session  );
184+ 		return  meta . persister .initializeEnhancedEntityUsedAsProxy ( target , attributeName , session  );
232185	}
233186
234187	@ Override 
@@ -237,19 +190,19 @@ protected Object handleWrite(Object target, String attributeName, Object oldValu
237190			throw  new  IllegalStateException ( "EnhancementAsProxyLazinessInterceptor interception on an initialized instance"  );
238191		}
239192
240- 		if  ( identifierAttributeNames .contains ( attributeName  ) ) {
193+ 		if  ( meta . identifierAttributeNames .contains ( attributeName  ) ) {
241194			// it is illegal for the identifier value to be changed.  Normally Hibernate 
242195			// validates this during flush.  However, here it's dangerous to just allow the 
243196			// new value to be set and continue on waiting for the flush for validation 
244197			// because this interceptor manages the entity's entry in the PC itself.  So 
245198			// just do the check here up-front 
246199			final  boolean  changed ;
247- 			if  ( nonAggregatedCidMapper  == null  ) {
200+ 			if  ( meta . nonAggregatedCidMapper  == null  ) {
248201				changed  = ! entityKey .getPersister ().getIdentifierType ().isEqual ( oldValue , newValue  );
249202			}
250203			else  {
251- 				final  int  subAttrIndex  = nonAggregatedCidMapper .getPropertyIndex ( attributeName  );
252- 				final  Type  subAttrType  = nonAggregatedCidMapper .getSubtypes ()[subAttrIndex ];
204+ 				final  int  subAttrIndex  = meta . nonAggregatedCidMapper .getPropertyIndex ( attributeName  );
205+ 				final  Type  subAttrType  = meta . nonAggregatedCidMapper .getSubtypes ()[subAttrIndex ];
253206				changed  = ! subAttrType .isEqual ( oldValue , newValue  );
254207			}
255208
@@ -262,8 +215,8 @@ protected Object handleWrite(Object target, String attributeName, Object oldValu
262215			return  newValue ;
263216		}
264217
265- 		if  ( initializeBeforeWrite 
266- 				|| collectionAttributeNames  != null  && collectionAttributeNames .contains ( attributeName  ) ) {
218+ 		if  ( meta . initializeBeforeWrite 
219+ 				|| meta . collectionAttributeNames  != null  && meta . collectionAttributeNames .contains ( attributeName  ) ) {
267220			// we need to force-initialize the proxy - the fetch group to which the `attributeName` belongs 
268221			try  {
269222				forceInitialize ( target , attributeName  );
@@ -272,7 +225,7 @@ protected Object handleWrite(Object target, String attributeName, Object oldValu
272225				setInitialized ();
273226			}
274227
275- 			if  ( inLineDirtyChecking  ) {
228+ 			if  ( meta . inLineDirtyChecking  ) {
276229				asSelfDirtinessTracker ( target  ).$$_hibernate_trackChange ( attributeName  );
277230			}
278231		}
@@ -310,7 +263,7 @@ public boolean isAttributeLoaded(String fieldName) {
310263			throw  new  UnsupportedOperationException ( "Call to EnhancementAsProxyLazinessInterceptor#isAttributeLoaded on an interceptor which is marked as initialized"  );
311264		}
312265		// Only fields from the identifier are loaded (until it's initialized) 
313- 		return  identifierAttributeNames .contains ( fieldName  );
266+ 		return  meta . identifierAttributeNames .contains ( fieldName  );
314267	}
315268
316269	@ Override 
@@ -352,4 +305,58 @@ private enum Status {
352305		INITIALIZING ,
353306		INITIALIZED 
354307	}
308+ 
309+ 	/** 
310+ 	 * This is an helper object to group all state which relates to a particular entity type, 
311+ 	 * and which is needed for this interceptor. 
312+ 	 * Grouping such state allows for upfront construction as a per-entity singleton: 
313+ 	 * this reduces processing work on creation of an interceptor instance and is more 
314+ 	 * efficient from a point of view of memory usage and memory layout. 
315+ 	 */ 
316+ 	public  static  class  EntityRelatedState  {
317+ 
318+ 		private  final  String  entityName ;
319+ 		private  final  CompositeType  nonAggregatedCidMapper ;
320+ 		private  final  Set <String > identifierAttributeNames ;
321+ 		private  final  Set <String > collectionAttributeNames ;
322+ 		private  final  boolean  initializeBeforeWrite ;
323+ 		private  final  boolean  inLineDirtyChecking ;
324+ 		private  final  EntityPersister  persister ;
325+ 
326+ 		public  EntityRelatedState (EntityPersister  persister ,
327+ 								CompositeType  nonAggregatedCidMapper ,
328+ 								Set <String > identifierAttributeNames ) {
329+ 			this .identifierAttributeNames  = identifierAttributeNames ;
330+ 			this .entityName  = persister .getEntityName ();
331+ 			this .nonAggregatedCidMapper  = nonAggregatedCidMapper ;
332+ 			this .persister  = persister ;
333+ 			assert  nonAggregatedCidMapper  != null  || identifierAttributeNames .size () == 1 ;
334+ 
335+ 			if  ( persister .hasCollections () ) {
336+ 				final  Set <String > tmpCollectionAttributeNames  = new  HashSet <>();
337+ 				final  Type [] propertyTypes  = persister .getPropertyTypes ();
338+ 				final  String [] propertyNames  = persister .getPropertyNames ();
339+ 				for  ( int  i  = 0 ; i  < propertyTypes .length ; i ++ ) {
340+ 					Type  propertyType  = propertyTypes [i ];
341+ 					if  ( propertyType  instanceof  CollectionType  ) {
342+ 						tmpCollectionAttributeNames .add ( propertyNames [i ] );
343+ 					}
344+ 				}
345+ 				this .collectionAttributeNames  = toSmallSet ( unmodifiableSet ( tmpCollectionAttributeNames  ) );
346+ 			}
347+ 			else  {
348+ 				this .collectionAttributeNames  = Collections .emptySet ();
349+ 			}
350+ 
351+ 			this .inLineDirtyChecking  = isSelfDirtinessTrackerType ( persister .getMappedClass () );
352+ 			// if self-dirty tracking is enabled but DynamicUpdate is not enabled then we need to 
353+ 			// initialize the entity because the precomputed update statement contains even not 
354+ 			// dirty properties. And so we need all the values we have to initialize. Or, if it's 
355+ 			// versioned, we need to fetch the current version. 
356+ 			this .initializeBeforeWrite  =
357+ 					!inLineDirtyChecking 
358+ 					|| !persister .getEntityMetamodel ().isDynamicUpdate ()
359+ 					|| persister .isVersioned ();
360+ 		}
361+ 	}
355362}
0 commit comments