Project

General

Profile

Revision 9ca50199

ID9ca50199408e528ef10d7b6019f3cfcea42dfec3
Parent e88eb110
Child cd024235

Added by Andreas Müller 2 months ago

ref #9204 update overridden AbstractPersistentCollection class to hibernate 5.1.17

View differences:

eu.etaxonomy.taxeditor.cdmlib/src/main/java/org/hibernate/collection/internal/AbstractPersistentCollection.java
34 34
import java.util.Iterator;
35 35
import java.util.List;
36 36
import java.util.ListIterator;
37
import java.util.Map;
37 38

  
38 39
import javax.naming.NamingException;
39 40

  
40 41
import org.hibernate.AssertionFailure;
42
import org.hibernate.FlushMode;
41 43
import org.hibernate.HibernateException;
42 44
import org.hibernate.LazyInitializationException;
43 45
import org.hibernate.Session;
46
import org.hibernate.collection.internal.AbstractPersistentCollection.DelayedOperation;
47
import org.hibernate.collection.internal.AbstractPersistentCollection.IteratorProxy;
48
import org.hibernate.collection.internal.AbstractPersistentCollection.LazyInitializationWork;
49
import org.hibernate.collection.internal.AbstractPersistentCollection.ListIteratorProxy;
50
import org.hibernate.collection.internal.AbstractPersistentCollection.ValueDelayedOperation;
44 51
import org.hibernate.collection.spi.PersistentCollection;
45 52
import org.hibernate.engine.internal.ForeignKeys;
46 53
import org.hibernate.engine.spi.CollectionEntry;
......
49 56
import org.hibernate.engine.spi.SessionImplementor;
50 57
import org.hibernate.engine.spi.Status;
51 58
import org.hibernate.engine.spi.TypedValue;
59
import org.hibernate.internal.CoreLogging;
60
import org.hibernate.internal.CoreMessageLogger;
52 61
import org.hibernate.internal.SessionFactoryRegistry;
53 62
import org.hibernate.internal.util.MarkerObject;
54 63
import org.hibernate.internal.util.collections.EmptyIterator;
......
56 65
import org.hibernate.persister.collection.CollectionPersister;
57 66
import org.hibernate.persister.entity.EntityPersister;
58 67
import org.hibernate.pretty.MessageHelper;
68
import org.hibernate.type.CompositeType;
69
import org.hibernate.type.IntegerType;
70
import org.hibernate.type.LongType;
71
import org.hibernate.type.PostgresUUIDType;
72
import org.hibernate.type.StringType;
59 73
import org.hibernate.type.Type;
74
import org.hibernate.type.UUIDBinaryType;
75
import org.hibernate.type.UUIDCharType;
60 76
import org.jboss.logging.Logger;
61 77

  
62 78
import eu.etaxonomy.cdm.api.application.CdmApplicationRemoteConfiguration;
......
68 84
/**
69 85
 * Base class implementing {@link org.hibernate.collection.spi.PersistentCollection}
70 86
 *
71
 * This a extended copy of the original class from hibernate. It has been extended to
87
 * This is an extended copy of the original class from hibernate. It has been extended to
72 88
 * allow making remote service calls to spring httpinvoker services (see section at the bottom
73 89
 * of this class).
74 90
 *
75
 *
76 91
 * @author Gavin King
77 92
 * @author Cherian Mathew
78 93
 */
79 94
public abstract class AbstractPersistentCollection implements Serializable, PersistentCollection {
80
	private static final Logger log = Logger.getLogger( AbstractPersistentCollection.class );
81

  
95
	
82 96
	/**
83 97
	 * <b>IMPORTANT:</b><br>
84 98
	 * This serialVersionUID must be kept in sync with the serialVersionUID which is generated
......
97 111
	 * The correct <code>serialVersionUID</code> is the <code>stream classdesc serialVersionUID</code>
98 112
	 * from the error message.
99 113
	 */
100
	private static final long serialVersionUID = 2742261122392386159L;
114
	private static final long serialVersionUID = 7094296207968006972L;
115

  
116
	private static final CoreMessageLogger LOG = CoreLogging.messageLogger( AbstractPersistentCollection.class );
101 117

  
102 118
	private transient SessionImplementor session;
119
	private boolean isTempSession = false;
103 120
	private boolean initialized;
104 121
	private transient List<DelayedOperation> operationQueue;
105 122
	private transient boolean directlyAccessible;
......
115 132
	private Serializable storedSnapshot;
116 133

  
117 134
	private String sessionFactoryUuid;
118
	private boolean specjLazyLoad = false;
135
	private boolean allowLoadOutsideTransaction;
136

  
137
	/**
138
	 * Not called by Hibernate, but used by non-JDK serialization,
139
	 * eg. SOAP libraries.
140
	 */
141
	public AbstractPersistentCollection() {
142
	}
143

  
144
	protected AbstractPersistentCollection(SessionImplementor session) {
145
		this.session = session;
146
	}
119 147

  
120 148
	@Override
121
    public final String getRole() {
149
	public final String getRole() {
122 150
		return role;
123 151
	}
124 152

  
125 153
	@Override
126
    public final Serializable getKey() {
154
	public final Serializable getKey() {
127 155
		return key;
128 156
	}
129 157

  
130 158
	@Override
131
    public final boolean isUnreferenced() {
159
	public final boolean isUnreferenced() {
132 160
		return role == null;
133 161
	}
134 162

  
135 163
	@Override
136
    public final boolean isDirty() {
164
	public final boolean isDirty() {
137 165
		return dirty;
138 166
	}
139 167

  
140 168
	@Override
141
    public final void clearDirty() {
169
	public final void clearDirty() {
142 170
		dirty = false;
143 171
	}
144 172

  
145 173
	@Override
146
    public final void dirty() {
174
	public final void dirty() {
147 175
		dirty = true;
148 176
	}
149 177

  
150 178
	@Override
151
    public final Serializable getStoredSnapshot() {
179
	public final Serializable getStoredSnapshot() {
152 180
		return storedSnapshot;
153 181
	}
154 182

  
155 183
	//Careful: these methods do not initialize the collection.
156 184

  
157
	/**
158
	 * Is the initialized collection empty?
159
	 */
160 185
	@Override
161
    public abstract boolean empty();
186
	public abstract boolean empty();
162 187

  
163 188
	/**
164 189
	 * Called by any read-only method of the collection interface
......
177 202
				return true;
178 203
			}
179 204
			else {
180
				// In remoting we are sure that session is null
181
				// both when using property paths and switching off conversations
182
				if(session == null && remoting) {
183
					log.info("--> readSize, of " + getRole() + " with key " + getKey());
184
					read();
185
				} else {
186
					boolean isExtraLazy = withTemporarySessionIfNeeded(
187
							new LazyInitializationWork<Boolean>() {
188
								@Override
189
								public Boolean doWork() {
190
									CollectionEntry entry = session.getPersistenceContext().getCollectionEntry( AbstractPersistentCollection.this );
191

  
192
									if ( entry != null ) {
193
										CollectionPersister persister = entry.getLoadedPersister();
194
										if ( persister.isExtraLazy() ) {
195
											if ( hasQueuedOperations() ) {
196
												session.flush();
197
											}
198
											cachedSize = persister.getSize( entry.getLoadedKey(), session );
199
											return true;
200
										}
201
										else {
202
											read();
205
				final boolean isExtraLazy = withTemporarySessionIfNeeded(
206
						new LazyInitializationWork<Boolean>() {
207
							@Override
208
							public Boolean doWork() {
209
								final CollectionEntry entry = session.getPersistenceContext().getCollectionEntry( AbstractPersistentCollection.this );
210

  
211
								if ( entry != null ) {
212
									final CollectionPersister persister = entry.getLoadedPersister();
213
									if ( persister.isExtraLazy() ) {
214
										if ( hasQueuedOperations() ) {
215
											session.flush();
203 216
										}
217
										cachedSize = persister.getSize( entry.getLoadedKey(), session );
218
										return true;
204 219
									}
205
									else{
206
										throwLazyInitializationExceptionIfNotConnected();
220
									else {
221
										read();
207 222
									}
208
									return false;
209 223
								}
224
								else{
225
									throwLazyInitializationExceptionIfNotConnected();
226
								}
227
								return false;
210 228
							}
211
							);
212
					if ( isExtraLazy ) {
213
						return true;
214
					}
229
						}
230
				);
231
				if ( isExtraLazy ) {
232
					return true;
215 233
				}
216 234
			}
217 235
		}
218 236
		return false;
219 237
	}
220 238

  
239
	/**
240
	 * TBH not sure why this is public
241
	 *
242
	 * @param <T> The java type of the return for this LazyInitializationWork
243
	 */
221 244
	public static interface LazyInitializationWork<T> {
245
		/**
246
		 * Do the represented work and return the result.
247
		 *
248
		 * @return The result
249
		 */
222 250
		public T doWork();
223 251
	}
224 252

  
225 253
	private <T> T withTemporarySessionIfNeeded(LazyInitializationWork<T> lazyInitializationWork) {
226
		SessionImplementor originalSession = null;
227
		boolean isTempSession = false;
228
		boolean isJTA = false;
254
		SessionImplementor tempSession = null;
229 255

  
230 256
		if ( session == null ) {
231
			if ( specjLazyLoad ) {
232
				session = openTemporarySessionForLoading();
233
				isTempSession = true;
257
			if ( allowLoadOutsideTransaction ) {
258
				tempSession = openTemporarySessionForLoading();
234 259
			}
235 260
			else {
236 261
				throwLazyInitializationException( "could not initialize proxy - no Session" );
237 262
			}
238 263
		}
239 264
		else if ( !session.isOpen() ) {
240
			if ( specjLazyLoad ) {
241
				originalSession = session;
242
				session = openTemporarySessionForLoading();
243
				isTempSession = true;
265
			if ( allowLoadOutsideTransaction ) {
266
				tempSession = openTemporarySessionForLoading();
244 267
			}
245 268
			else {
246 269
				throwLazyInitializationException( "could not initialize proxy - the owning Session was closed" );
247 270
			}
248 271
		}
249 272
		else if ( !session.isConnected() ) {
250
			if ( specjLazyLoad ) {
251
				originalSession = session;
252
				session = openTemporarySessionForLoading();
253
				isTempSession = true;
273
			if ( allowLoadOutsideTransaction ) {
274
				tempSession = openTemporarySessionForLoading();
254 275
			}
255 276
			else {
256 277
				throwLazyInitializationException( "could not initialize proxy - the owning Session is disconnected" );
257 278
			}
258 279
		}
259 280

  
260
		if ( isTempSession ) {
261
			// TODO: On the next major release, add an
262
			// 'isJTA' or 'getTransactionFactory' method to Session.
263
			/*isJTA = session.getTransactionCoordinator()
264
					.getTransactionContext().getTransactionEnvironment()
265
					.getTransactionFactory()
266
					.compatibleWithJtaSynchronization();*/
281

  
282
		SessionImplementor originalSession = null;
283
		boolean isJTA = false;
284

  
285
		if ( tempSession != null ) {
286
			isTempSession = true;
287
			originalSession = session;
288
			session = tempSession;
289

  
290

  
267 291
			isJTA = session.getTransactionCoordinator().getTransactionCoordinatorBuilder().isJta();
292
			
268 293
			if ( !isJTA ) {
269 294
				// Explicitly handle the transactions only if we're not in
270 295
				// a JTA environment.  A lazy loading temporary session can
271 296
				// be created even if a current session and transaction are
272 297
				// open (ex: session.clear() was used).  We must prevent
273 298
				// multiple transactions.
274
				( ( Session) session ).beginTransaction();
299
				( (Session) session ).beginTransaction();
275 300
			}
276 301

  
277 302
			session.getPersistenceContext().addUninitializedDetachedCollection(
......
284 309
			return lazyInitializationWork.doWork();
285 310
		}
286 311
		finally {
287
			if ( isTempSession ) {
312
			if ( tempSession != null ) {
288 313
				// make sure the just opened temp session gets closed!
314
				isTempSession = false;
315
				session = originalSession;
316

  
289 317
				try {
290 318
					if ( !isJTA ) {
291
						( ( Session) session ).getTransaction().commit();
319
						( (Session) tempSession ).getTransaction().commit();
292 320
					}
293
					( (Session) session ).close();
321
					( (Session) tempSession ).close();
294 322
				}
295 323
				catch (Exception e) {
296
					log.warn( "Unable to close temporary session used to load lazy collection associated to no session" );
324
					LOG.warn( "Unable to close temporary session used to load lazy collection associated to no session" );
297 325
				}
298
				session = originalSession;
299 326
			}
300 327
		}
301 328
	}
......
305 332
			throwLazyInitializationException( "SessionFactory UUID not known to create temporary Session for loading" );
306 333
		}
307 334

  
308
		SessionFactoryImplementor sf = (SessionFactoryImplementor)
335
		final SessionFactoryImplementor sf = (SessionFactoryImplementor)
309 336
				SessionFactoryRegistry.INSTANCE.getSessionFactory( sessionFactoryUuid );
310
		return (SessionImplementor) sf.openSession();
337
		final SessionImplementor session = (SessionImplementor) sf.openSession();
338
		session.getPersistenceContext().setDefaultReadOnly( true );
339
		session.setFlushMode( FlushMode.MANUAL );
340
		return session;
311 341
	}
312 342

  
313 343
	protected Boolean readIndexExistence(final Object index) {
314 344
		if ( !initialized ) {
315
			// In remoting we are sure that session is null
316
			// both when using property paths and switching off conversations
317
			if(session == null && remoting) {
318
				log.info("--> readIndexExistence, of " + getRole() + " with key " + getKey());
319
				read();
320
			} else {
321
				Boolean extraLazyExistenceCheck = withTemporarySessionIfNeeded(
322
						new LazyInitializationWork<Boolean>() {
323
							@Override
324
							public Boolean doWork() {
325
								CollectionEntry entry = session.getPersistenceContext().getCollectionEntry( AbstractPersistentCollection.this );
326
								CollectionPersister persister = entry.getLoadedPersister();
327
								if ( persister.isExtraLazy() ) {
328
									if ( hasQueuedOperations() ) {
329
										session.flush();
330
									}
331
									return persister.indexExists( entry.getLoadedKey(), index, session );
332
								}
333
								else {
334
									read();
345
			final Boolean extraLazyExistenceCheck = withTemporarySessionIfNeeded(
346
					new LazyInitializationWork<Boolean>() {
347
						@Override
348
						public Boolean doWork() {
349
							final CollectionEntry entry = session.getPersistenceContext().getCollectionEntry( AbstractPersistentCollection.this );
350
							final CollectionPersister persister = entry.getLoadedPersister();
351
							if ( persister.isExtraLazy() ) {
352
								if ( hasQueuedOperations() ) {
353
									session.flush();
335 354
								}
336
								return null;
355
								return persister.indexExists( entry.getLoadedKey(), index, session );
356
							}
357
							else {
358
								read();
337 359
							}
360
							return null;
338 361
						}
339
						);
340
				if ( extraLazyExistenceCheck != null ) {
341
					return extraLazyExistenceCheck;
342
				}
362
					}
363
			);
364
			if ( extraLazyExistenceCheck != null ) {
365
				return extraLazyExistenceCheck;
343 366
			}
344 367
		}
345 368
		return null;
......
347 370

  
348 371
	protected Boolean readElementExistence(final Object element) {
349 372
		if ( !initialized ) {
350
			// In remoting we are sure that session is null
351
			// both when using property paths and switching off conversations
352
			if(session == null && remoting) {
353
				log.info("--> readElementExistence, of " + getRole() + " with key " + getKey());
354
				read();
355

  
356
			} else {
357
				Boolean extraLazyExistenceCheck = withTemporarySessionIfNeeded(
358
						new LazyInitializationWork<Boolean>() {
359
							@Override
360
							public Boolean doWork() {
361
								CollectionEntry entry = session.getPersistenceContext().getCollectionEntry( AbstractPersistentCollection.this );
362
								CollectionPersister persister = entry.getLoadedPersister();
363
								if ( persister.isExtraLazy() ) {
364
									if ( hasQueuedOperations() ) {
365
										session.flush();
366
									}
367
									return persister.elementExists( entry.getLoadedKey(), element, session );
368
								}
369
								else {
370
									read();
373
			final Boolean extraLazyExistenceCheck = withTemporarySessionIfNeeded(
374
					new LazyInitializationWork<Boolean>() {
375
						@Override
376
						public Boolean doWork() {
377
							final CollectionEntry entry = session.getPersistenceContext().getCollectionEntry( AbstractPersistentCollection.this );
378
							final CollectionPersister persister = entry.getLoadedPersister();
379
							if ( persister.isExtraLazy() ) {
380
								if ( hasQueuedOperations() ) {
381
									session.flush();
371 382
								}
372
								return null;
383
								return persister.elementExists( entry.getLoadedKey(), element, session );
373 384
							}
385
							else {
386
								read();
387
							}
388
							return null;
374 389
						}
375
						);
376
				if ( extraLazyExistenceCheck != null ) {
377
					return extraLazyExistenceCheck;
378
				}
390
					}
391
			);
392
			if ( extraLazyExistenceCheck != null ) {
393
				return extraLazyExistenceCheck;
379 394
			}
380 395
		}
381 396
		return null;
......
385 400

  
386 401
	protected Object readElementByIndex(final Object index) {
387 402
		if ( !initialized ) {
388
			// In remoting we are sure that session is null
389
			// both when using property paths and switching off conversations
390
			if(session == null && remoting) {
391
				log.info("--> readElementByIndex, of " + getRole() + " with key " + getKey());
392
				read();
393

  
394
			} else {
395
				class ExtraLazyElementByIndexReader implements LazyInitializationWork {
396
					private boolean isExtraLazy;
397
					private Object element;
403
			class ExtraLazyElementByIndexReader implements LazyInitializationWork {
404
				private boolean isExtraLazy;
405
				private Object element;
398 406

  
399
					@Override
400
					public Object doWork() {
401
						CollectionEntry entry = session.getPersistenceContext().getCollectionEntry( AbstractPersistentCollection.this );
402
						CollectionPersister persister = entry.getLoadedPersister();
403
						isExtraLazy = persister.isExtraLazy();
404
						if ( isExtraLazy ) {
405
							if ( hasQueuedOperations() ) {
406
								session.flush();
407
							}
408
							element = persister.getElementByIndex( entry.getLoadedKey(), index, session, owner );
409
						}
410
						else {
411
							read();
407
				@Override
408
				public Object doWork() {
409
					final CollectionEntry entry = session.getPersistenceContext().getCollectionEntry( AbstractPersistentCollection.this );
410
					final CollectionPersister persister = entry.getLoadedPersister();
411
					isExtraLazy = persister.isExtraLazy();
412
					if ( isExtraLazy ) {
413
						if ( hasQueuedOperations() ) {
414
							session.flush();
412 415
						}
413
						return null;
416
						element = persister.getElementByIndex( entry.getLoadedKey(), index, session, owner );
414 417
					}
418
					else {
419
						read();
420
					}
421
					return null;
415 422
				}
423
			}
416 424

  
417
				ExtraLazyElementByIndexReader reader = new ExtraLazyElementByIndexReader();
418
				//noinspection unchecked
419
				withTemporarySessionIfNeeded( reader );
420
				if ( reader.isExtraLazy ) {
421
					return reader.element;
422
				}
425
			final ExtraLazyElementByIndexReader reader = new ExtraLazyElementByIndexReader();
426
			//noinspection unchecked
427
			withTemporarySessionIfNeeded( reader );
428
			if ( reader.isExtraLazy ) {
429
				return reader.element;
423 430
			}
424 431
		}
425 432
		return UNKNOWN;
......
430 437
		return cachedSize;
431 438
	}
432 439

  
433
	private boolean isConnectedToSession() {
434
		return session != null &&
435
				session.isOpen() &&
436
				session.getPersistenceContext().containsCollection( this );
440
	protected boolean isConnectedToSession() {
441
		return session != null
442
				&& session.isOpen()
443
				&& session.getPersistenceContext().containsCollection( this );
444
	}
445

  
446
	protected boolean isInitialized() {
447
		return initialized;
437 448
	}
438 449

  
439 450
	/**
......
450 461
	 */
451 462
	@SuppressWarnings({"JavaDoc"})
452 463
	protected boolean isOperationQueueEnabled() {
453
		return !initialized &&
454
				isConnectedToSession() &&
455
				isInverseCollection();
464
		return !initialized
465
				&& isConnectedToSession()
466
				&& isInverseCollection();
456 467
	}
457 468

  
458 469
	/**
......
462 473
	 */
463 474
	@SuppressWarnings({"JavaDoc"})
464 475
	protected boolean isPutQueueEnabled() {
465
		return !initialized &&
466
				isConnectedToSession() &&
467
				isInverseOneToManyOrNoOrphanDelete();
476
		return !initialized
477
				&& isConnectedToSession()
478
				&& isInverseOneToManyOrNoOrphanDelete();
468 479
	}
469 480

  
470 481
	/**
......
474 485
	 */
475 486
	@SuppressWarnings({"JavaDoc"})
476 487
	protected boolean isClearQueueEnabled() {
477
		return !initialized &&
478
				isConnectedToSession() &&
479
				isInverseCollectionNoOrphanDelete();
488
		return !initialized
489
				&& isConnectedToSession()
490
				&& isInverseCollectionNoOrphanDelete();
480 491
	}
481 492

  
482 493
	/**
483 494
	 * Is this the "inverse" end of a bidirectional association?
484 495
	 */
485 496
	@SuppressWarnings({"JavaDoc"})
486
	private boolean isInverseCollection() {
487
		CollectionEntry ce = session.getPersistenceContext().getCollectionEntry( this );
497
	protected boolean isInverseCollection() {
498
		final CollectionEntry ce = session.getPersistenceContext().getCollectionEntry( this );
488 499
		return ce != null && ce.getLoadedPersister().isInverse();
489 500
	}
490 501

  
......
493 504
	 * no orphan delete enabled?
494 505
	 */
495 506
	@SuppressWarnings({"JavaDoc"})
496
	private boolean isInverseCollectionNoOrphanDelete() {
497
		CollectionEntry ce = session.getPersistenceContext().getCollectionEntry( this );
498
		return ce != null &&
507
	protected boolean isInverseCollectionNoOrphanDelete() {
508
		final CollectionEntry ce = session.getPersistenceContext().getCollectionEntry( this );
509
		return ce != null
510
				&&
499 511
				ce.getLoadedPersister().isInverse() &&
500 512
				!ce.getLoadedPersister().hasOrphanDelete();
501 513
	}
......
505 517
	 * of a collection with no orphan delete?
506 518
	 */
507 519
	@SuppressWarnings({"JavaDoc"})
508
	private boolean isInverseOneToManyOrNoOrphanDelete() {
509
		CollectionEntry ce = session.getPersistenceContext().getCollectionEntry( this );
510
		return ce != null && ce.getLoadedPersister().isInverse() && (
511
				ce.getLoadedPersister().isOneToMany() ||
512
						!ce.getLoadedPersister().hasOrphanDelete()
513
		);
520
	protected boolean isInverseOneToManyOrNoOrphanDelete() {
521
		final CollectionEntry ce = session.getPersistenceContext().getCollectionEntry( this );
522
		return ce != null
523
				&& ce.getLoadedPersister().isInverse()
524
				&& ( ce.getLoadedPersister().isOneToMany() || !ce.getLoadedPersister().hasOrphanDelete() );
514 525
	}
515 526

  
516 527
	/**
......
522 533
			operationQueue = new ArrayList<DelayedOperation>( 10 );
523 534
		}
524 535
		operationQueue.add( operation );
525
		dirty = true; //needed so that we remove this collection from the second-level cache
536
		//needed so that we remove this collection from the second-level cache
537
		dirty = true;
538
	}
539

  
540
	/**
541
	 * Replace entity instances with copy in {@code copyCache}/.
542
	 *
543
	 * @param copyCache - mapping from entity in the process of being
544
	 *                    merged to managed copy.
545
	 */
546
	public final void replaceQueuedOperationValues(CollectionPersister persister, Map copyCache) {
547
		for ( DelayedOperation operation : operationQueue ) {
548
			if ( ValueDelayedOperation.class.isInstance( operation ) ) {
549
				( (ValueDelayedOperation) operation ).replace( persister, copyCache );
550
			}
551
		}
526 552
	}
527 553

  
528 554
	/**
......
535 561
		}
536 562
	}
537 563

  
538
	/**
539
	 * After flushing, re-init snapshot state.
540
	 */
541 564
	@Override
542
    public void setSnapshot(Serializable key, String role, Serializable snapshot) {
565
	public void setSnapshot(Serializable key, String role, Serializable snapshot) {
543 566
		this.key = key;
544 567
		this.role = role;
545 568
		this.storedSnapshot = snapshot;
546 569
	}
547 570

  
548
	/**
549
	 * After flushing, clear any "queued" additions, since the
550
	 * database state is now synchronized with the memory state.
551
	 */
552 571
	@Override
553
    public void postAction() {
572
	public void postAction() {
554 573
		operationQueue = null;
555 574
		cachedSize = -1;
556 575
		clearDirty();
557 576
	}
558 577

  
559
	/**
560
	 * Not called by Hibernate, but used by non-JDK serialization,
561
	 * eg. SOAP libraries.
562
	 */
563
	public AbstractPersistentCollection() {
564
	}
565

  
566
	protected AbstractPersistentCollection(SessionImplementor session) {
567
		this.session = session;
568
	}
569

  
570
	/**
571
	 * return the user-visible collection (or array) instance
572
	 */
573 578
	@Override
574
    public Object getValue() {
579
	public Object getValue() {
575 580
		return this;
576 581
	}
577 582

  
578
	/**
579
	 * Called just before reading any rows from the JDBC result set
580
	 */
581 583
	@Override
582
    public void beginRead() {
584
	public void beginRead() {
583 585
		// override on some subclasses
584 586
		initializing = true;
585 587
	}
586 588

  
587
	/**
588
	 * Called after reading all rows from the JDBC result set
589
	 */
590 589
	@Override
591
    public boolean endRead() {
590
	public boolean endRead() {
592 591
		//override on some subclasses
593 592
		return afterInitialize();
594 593
	}
595 594

  
596 595
	@Override
597
    public boolean afterInitialize() {
596
	public boolean afterInitialize() {
598 597
		setInitialized();
599 598
		//do this bit after setting initialized to true or it will recurse
600 599
		if ( operationQueue != null ) {
......
617 616
	 * @throws LazyInitializationException if we cannot initialize
618 617
	 */
619 618
	protected final void initialize(final boolean writing) {
620
	    if ( initialized ) {
621
	        return;
622
	    }
623

  
624
	    // In remoting we are sure that session is null
625
	    // both when using property paths and switching off conversations
626
	    if(session == null && remoting) {
627
	        remoteInitialize();
628
	    } else {
629
	        withTemporarySessionIfNeeded(
630
	                new LazyInitializationWork<Object>() {
631
	                    @Override
632
	                    public Object doWork() {
633
	                        session.initializeCollection( AbstractPersistentCollection.this, writing );
634
	                        return null;
635
	                    }
636
	                }
637
	                );
638
	    }
619
		if ( initialized ) {
620
			return;
621
		}
622

  
623
		withTemporarySessionIfNeeded(
624
				new LazyInitializationWork<Object>() {
625
					@Override
626
					public Object doWork() {
627
						session.initializeCollection( AbstractPersistentCollection.this, writing );
628
						return null;
629
					}
630
				}
631
		);
639 632
	}
640 633

  
641 634
	private void throwLazyInitializationExceptionIfNotConnected() {
......
664 657
		this.directlyAccessible = directlyAccessible;
665 658
	}
666 659

  
667
	/**
668
	 * Could the application possibly have a direct reference to
669
	 * the underlying collection implementation?
670
	 */
671 660
	@Override
672
    public boolean isDirectlyAccessible() {
661
	public boolean isDirectlyAccessible() {
673 662
		return directlyAccessible;
674 663
	}
675 664

  
676
	/**
677
	 * Disassociate this collection from the given session.
678
	 *
679
	 * @return true if this was currently associated with the given session
680
	 */
681 665
	@Override
682
    public final boolean unsetSession(SessionImplementor currentSession) {
683
		prepareForPossibleSpecialSpecjInitialization();
666
	public final boolean unsetSession(SessionImplementor currentSession) {
667
		prepareForPossibleLoadingOutsideTransaction();
684 668
		if ( currentSession == this.session ) {
685
			this.session = null;
669
			if ( !isTempSession ) {
670
				this.session = null;
671
			}
686 672
			return true;
687 673
		}
688 674
		else {
675
			if ( this.session != null ) {
676
				LOG.logCannotUnsetUnexpectedSessionInCollection( generateUnexpectedSessionStateMessage( currentSession ) );
677
			}
689 678
			return false;
690 679
		}
691 680
	}
692 681

  
693
	protected void prepareForPossibleSpecialSpecjInitialization() {
682
	protected void prepareForPossibleLoadingOutsideTransaction() {
694 683
		if ( session != null ) {
695
			specjLazyLoad = session.getFactory().getSettings().isInitializeLazyStateOutsideTransactionsEnabled();
684
			allowLoadOutsideTransaction = session.getFactory().getSessionFactoryOptions().isInitializeLazyStateOutsideTransactionsEnabled();
696 685

  
697
			if ( specjLazyLoad && sessionFactoryUuid == null ) {
698
				try {
699
					sessionFactoryUuid = (String) session.getFactory().getReference().get( "uuid" ).getContent();
700
				}
701
				catch (NamingException e) {
702
					//not much we can do if this fails...
703
				}
686
			if ( allowLoadOutsideTransaction && sessionFactoryUuid == null ) {
687
				sessionFactoryUuid = session.getFactory().getUuid();
704 688
			}
705 689
		}
706 690
	}
707 691

  
708

  
709
	/**
710
	 * Associate the collection with the given session.
711
	 *
712
	 * @return false if the collection was already associated with the session
713
	 *
714
	 * @throws HibernateException if the collection was already associated
715
	 * with another open session
716
	 */
717 692
	@Override
718
    public final boolean setCurrentSession(SessionImplementor session) throws HibernateException {
693
	public final boolean setCurrentSession(SessionImplementor session) throws HibernateException {
719 694
		if ( session == this.session ) {
720 695
			return false;
721 696
		}
722 697
		else {
723
			if ( isConnectedToSession() ) {
724
				CollectionEntry ce = session.getPersistenceContext().getCollectionEntry( this );
725
				if ( ce == null ) {
698
			if ( this.session != null ) {
699
				final String msg = generateUnexpectedSessionStateMessage( session );
700
				if ( isConnectedToSession() ) {
726 701
					throw new HibernateException(
727
							"Illegal attempt to associate a collection with two open sessions"
702
							"Illegal attempt to associate a collection with two open sessions. " + msg
728 703
					);
729 704
				}
730 705
				else {
731
					throw new HibernateException(
732
							"Illegal attempt to associate a collection with two open sessions: " +
733
									MessageHelper.collectionInfoString(
734
											ce.getLoadedPersister(), this,
735
											ce.getLoadedKey(), session
736
									)
737
					);
706
					LOG.logUnexpectedSessionInCollectionNotConnected( msg );
707
					this.session = session;
708
					return true;
738 709
				}
739 710
			}
740 711
			else {
......
744 715
		}
745 716
	}
746 717

  
747
	/**
748
	 * Do we need to completely recreate this collection when it changes?
749
	 */
718
	private String generateUnexpectedSessionStateMessage(SessionImplementor session) {
719
		// NOTE: If this.session != null, this.session may be operating on this collection
720
		// (e.g., by changing this.role, this.key, or even this.session) in a different thread.
721

  
722
		// Grab the current role and key (it can still get changed by this.session...)
723
		// If this collection is connected to this.session, then this.role and this.key should
724
		// be consistent with the CollectionEntry in this.session (as long as this.session doesn't
725
		// change it). Don't access the CollectionEntry in this.session because that could result
726
		// in multi-threaded access to this.session.
727
		final String roleCurrent = role;
728
		final Serializable keyCurrent = key;
729

  
730
		final StringBuilder sb = new StringBuilder( "Collection : " );
731
		if ( roleCurrent != null ) {
732
			sb.append( MessageHelper.collectionInfoString( roleCurrent, keyCurrent ) );
733
		}
734
		else {
735
			final CollectionEntry ce = session.getPersistenceContext().getCollectionEntry( this );
736
			if ( ce != null ) {
737
				sb.append(
738
						MessageHelper.collectionInfoString(
739
								ce.getLoadedPersister(),
740
								this,
741
								ce.getLoadedKey(),
742
								session
743
						)
744
				);
745
			}
746
			else {
747
				sb.append( "<unknown>" );
748
			}
749
		}
750
		// only include the collection contents if debug logging
751
		if ( LOG.isDebugEnabled() ) {
752
			final String collectionContents = wasInitialized() ? toString() : "<uninitialized>";
753
			sb.append( "\nCollection contents: [" ).append( collectionContents ).append( "]" );
754
		}
755
		return sb.toString();
756
	}
757

  
750 758
	@Override
751
    public boolean needsRecreate(CollectionPersister persister) {
759
	public boolean needsRecreate(CollectionPersister persister) {
760
		// Workaround for situations like HHH-7072.  If the collection element is a component that consists entirely
761
		// of nullable properties, we currently have to forcefully recreate the entire collection.  See the use
762
		// of hasNotNullableColumns in the AbstractCollectionPersister constructor for more info.  In order to delete
763
		// row-by-row, that would require SQL like "WHERE ( COL = ? OR ( COL is null AND ? is null ) )", rather than
764
		// the current "WHERE COL = ?" (fails for null for most DBs).  Note that
765
		// the param would have to be bound twice.  Until we eventually add "parameter bind points" concepts to the
766
		// AST in ORM 5+, handling this type of condition is either extremely difficult or impossible.  Forcing
767
		// recreation isn't ideal, but not really any other option in ORM 4.
768
		// Selecting a type used in where part of update statement
769
		// (must match condidion in org.hibernate.persister.collection.BasicCollectionPersister.doUpdateRows).
770
		// See HHH-9474
771
		Type whereType;
772
		if ( persister.hasIndex() ) {
773
			whereType = persister.getIndexType();
774
		}
775
		else {
776
			whereType = persister.getElementType();
777
		}
778
		if ( whereType instanceof CompositeType ) {
779
			CompositeType componentIndexType = (CompositeType) whereType;
780
			return !componentIndexType.hasNotNullProperty();
781
		}
752 782
		return false;
753 783
	}
754 784

  
755
	/**
756
	 * To be called internally by the session, forcing
757
	 * immediate initialization.
758
	 */
759 785
	@Override
760
    public final void forceInitialization() throws HibernateException {
786
	public final void forceInitialization() throws HibernateException {
761 787
		if ( !initialized ) {
762 788
			if ( initializing ) {
763 789
				throw new AssertionFailure( "force initialize loading collection" );
764 790
			}
765
			if ( session == null ) {
766
				throw new HibernateException( "collection is not associated with any session" );
767
			}
768
			if ( !session.isConnected() ) {
769
				throw new HibernateException( "disconnected session" );
770
			}
771
			session.initializeCollection( this, false );
791
			initialize( false );
772 792
		}
773 793
	}
774 794

  
......
781 801
		return session.getPersistenceContext().getSnapshot( this );
782 802
	}
783 803

  
784
	/**
785
	 * Is this instance initialized?
786
	 */
787 804
	@Override
788
    public final boolean wasInitialized() {
805
	public final boolean wasInitialized() {
789 806
		return initialized;
790 807
	}
791 808

  
792 809
	@Override
793
    public boolean isRowUpdatePossible() {
810
	public boolean isRowUpdatePossible() {
794 811
		return true;
795 812
	}
796 813

  
797
	/**
798
	 * Does this instance have any "queued" additions?
799
	 */
800 814
	@Override
801
    public final boolean hasQueuedOperations() {
815
	public final boolean hasQueuedOperations() {
802 816
		return operationQueue != null;
803 817
	}
804 818

  
805
	/**
806
	 * Iterate the "queued" additions
807
	 */
808 819
	@Override
809
    public final Iterator queuedAdditionIterator() {
820
	public final Iterator queuedAdditionIterator() {
810 821
		if ( hasQueuedOperations() ) {
811 822
			return new Iterator() {
812
				int i = 0;
823
				private int index;
813 824

  
814 825
				@Override
815
                public Object next() {
816
					return operationQueue.get( i++ ).getAddedInstance();
826
				public Object next() {
827
					return operationQueue.get( index++ ).getAddedInstance();
817 828
				}
818 829

  
819 830
				@Override
820
                public boolean hasNext() {
821
					return i < operationQueue.size();
831
				public boolean hasNext() {
832
					return index < operationQueue.size();
822 833
				}
823 834

  
824 835
				@Override
825
                public void remove() {
836
				public void remove() {
826 837
					throw new UnsupportedOperationException();
827 838
				}
828 839
			};
......
832 843
		}
833 844
	}
834 845

  
835
	/**
836
	 * Iterate the "queued" additions
837
	 */
838 846
	@Override
839
    @SuppressWarnings({"unchecked"})
847
	@SuppressWarnings({"unchecked"})
840 848
	public final Collection getQueuedOrphans(String entityName) {
841 849
		if ( hasQueuedOperations() ) {
842
			Collection additions = new ArrayList( operationQueue.size() );
843
			Collection removals = new ArrayList( operationQueue.size() );
850
			final Collection additions = new ArrayList( operationQueue.size() );
851
			final Collection removals = new ArrayList( operationQueue.size() );
844 852
			for ( DelayedOperation operation : operationQueue ) {
845 853
				additions.add( operation.getAddedInstance() );
846 854
				removals.add( operation.getOrphan() );
......
852 860
		}
853 861
	}
854 862

  
855
	/**
856
	 * Called before inserting rows, to ensure that any surrogate keys
857
	 * are fully generated
858
	 */
859 863
	@Override
860
    public void preInsert(CollectionPersister persister) throws HibernateException {
864
	public void preInsert(CollectionPersister persister) throws HibernateException {
861 865
	}
862 866

  
863
	/**
864
	 * Called after inserting a row, to fetch the natively generated id
865
	 */
866 867
	@Override
867
    public void afterRowInsert(CollectionPersister persister, Object entry, int i) throws HibernateException {
868
	public void afterRowInsert(CollectionPersister persister, Object entry, int i) throws HibernateException {
868 869
	}
869 870

  
870
	/**
871
	 * get all "orphaned" elements
872
	 */
873 871
	@Override
874
    public abstract Collection getOrphans(Serializable snapshot, String entityName) throws HibernateException;
872
	public abstract Collection getOrphans(Serializable snapshot, String entityName) throws HibernateException;
875 873

  
876 874
	/**
877
	 * Get the current session
875
	 * Get the session currently associated with this collection.
876
	 *
877
	 * @return The session
878 878
	 */
879
	@SuppressWarnings({"JavaDoc"})
880 879
	public final SessionImplementor getSession() {
881 880
		return session;
882 881
	}
......
889 888
		}
890 889

  
891 890
		@Override
892
        public boolean hasNext() {
891
		public boolean hasNext() {
893 892
			return itr.hasNext();
894 893
		}
895 894

  
896 895
		@Override
897
        public Object next() {
896
		public Object next() {
898 897
			return itr.next();
899 898
		}
900 899

  
901 900
		@Override
902
        public void remove() {
901
		public void remove() {
903 902
			write();
904 903
			itr.remove();
905 904
		}
906

  
907 905
	}
908 906

  
909 907
	protected final class ListIteratorProxy implements ListIterator {
......
914 912
		}
915 913

  
916 914
		@Override
917
        @SuppressWarnings({"unchecked"})
915
		@SuppressWarnings({"unchecked"})
918 916
		public void add(Object o) {
919 917
			write();
920 918
			itr.add( o );
921 919
		}
922 920

  
923 921
		@Override
924
        public boolean hasNext() {
922
		public boolean hasNext() {
925 923
			return itr.hasNext();
926 924
		}
927 925

  
928 926
		@Override
929
        public boolean hasPrevious() {
927
		public boolean hasPrevious() {
930 928
			return itr.hasPrevious();
931 929
		}
932 930

  
933 931
		@Override
934
        public Object next() {
932
		public Object next() {
935 933
			return itr.next();
936 934
		}
937 935

  
938 936
		@Override
939
        public int nextIndex() {
937
		public int nextIndex() {
940 938
			return itr.nextIndex();
941 939
		}
942 940

  
943 941
		@Override
944
        public Object previous() {
942
		public Object previous() {
945 943
			return itr.previous();
946 944
		}
947 945

  
948 946
		@Override
949
        public int previousIndex() {
947
		public int previousIndex() {
950 948
			return itr.previousIndex();
951 949
		}
952 950

  
953 951
		@Override
954
        public void remove() {
952
		public void remove() {
955 953
			write();
956 954
			itr.remove();
957 955
		}
958 956

  
959 957
		@Override
960
        @SuppressWarnings({"unchecked"})
958
		@SuppressWarnings({"unchecked"})
961 959
		public void set(Object o) {
962 960
			write();
963 961
			itr.set( o );
964 962
		}
965

  
966 963
	}
967 964

  
968 965
	protected class SetProxy implements java.util.Set {
......
973 970
		}
974 971

  
975 972
		@Override
976
        @SuppressWarnings({"unchecked"})
973
		@SuppressWarnings({"unchecked"})
977 974
		public boolean add(Object o) {
978 975
			write();
979 976
			return set.add( o );
980 977
		}
981 978

  
982 979
		@Override
983
        @SuppressWarnings({"unchecked"})
980
		@SuppressWarnings({"unchecked"})
984 981
		public boolean addAll(Collection c) {
985 982
			write();
986 983
			return set.addAll( c );
987 984
		}
988 985

  
989 986
		@Override
990
        public void clear() {
987
		public void clear() {
991 988
			write();
992 989
			set.clear();
993 990
		}
994 991

  
995 992
		@Override
996
        public boolean contains(Object o) {
993
		public boolean contains(Object o) {
997 994
			return set.contains( o );
998 995
		}
999 996

  
1000 997
		@Override
1001
        public boolean containsAll(Collection c) {
998
		@SuppressWarnings("unchecked")
999
		public boolean containsAll(Collection c) {
1002 1000
			return set.containsAll( c );
1003 1001
		}
1004 1002

  
1005 1003
		@Override
1006
        public boolean isEmpty() {
1004
		public boolean isEmpty() {
1007 1005
			return set.isEmpty();
1008 1006
		}
1009 1007

  
1010 1008
		@Override
1011
        public Iterator iterator() {
1009
		public Iterator iterator() {
1012 1010
			return new IteratorProxy( set.iterator() );
1013 1011
		}
1014 1012

  
1015 1013
		@Override
1016
        public boolean remove(Object o) {
1014
		public boolean remove(Object o) {
1017 1015
			write();
1018 1016
			return set.remove( o );
1019 1017
		}
1020 1018

  
1021 1019
		@Override
1022
        public boolean removeAll(Collection c) {
1020
		@SuppressWarnings("unchecked")
1021
		public boolean removeAll(Collection c) {
1023 1022
			write();
1024 1023
			return set.removeAll( c );
1025 1024
		}
1026 1025

  
1027 1026
		@Override
1028
        public boolean retainAll(Collection c) {
1027
		@SuppressWarnings("unchecked")
1028
		public boolean retainAll(Collection c) {
1029 1029
			write();
1030 1030
			return set.retainAll( c );
1031 1031
		}
1032 1032

  
1033 1033
		@Override
1034
        public int size() {
1034
		public int size() {
1035 1035
			return set.size();
1036 1036
		}
1037 1037

  
1038 1038
		@Override
1039
        public Object[] toArray() {
1039
		public Object[] toArray() {
1040 1040
			return set.toArray();
1041 1041
		}
1042 1042

  
1043 1043
		@Override
1044
        @SuppressWarnings({"unchecked"})
1044
		@SuppressWarnings({"unchecked"})
1045 1045
		public Object[] toArray(Object[] array) {
1046 1046
			return set.toArray( array );
1047 1047
		}
1048

  
1049 1048
	}
1050 1049

  
1051 1050
	protected final class ListProxy implements java.util.List {
......
1095 1094
		}
1096 1095

  
1097 1096
		@Override
1097
		@SuppressWarnings("unchecked")
1098 1098
		public boolean containsAll(Collection c) {
1099 1099
			return list.containsAll( c );
1100 1100
		}
......
1147 1147
		}
1148 1148

  
1149 1149
		@Override
1150
		@SuppressWarnings("unchecked")
1150 1151
		public boolean removeAll(Collection c) {
1151 1152
			write();
1152 1153
			return list.removeAll( c );
1153 1154
		}
1154 1155

  
1155 1156
		@Override
1157
		@SuppressWarnings("unchecked")
1156 1158
		public boolean retainAll(Collection c) {
1157 1159
			write();
1158 1160
			return list.retainAll( c );
......
1199 1201
		public Object getOrphan();
1200 1202
	}
1201 1203

  
1204
	protected interface ValueDelayedOperation extends DelayedOperation {
1205
		void replace(CollectionPersister collectionPersister, Map copyCache);
1206
	}
1207

  
1208
	protected abstract class AbstractValueDelayedOperation implements ValueDelayedOperation {
1209
		private Object addedValue;
1210
		private Object orphan;
1211

  
1212
		protected AbstractValueDelayedOperation(Object addedValue, Object orphan) {
1213
			this.addedValue = addedValue;
1214
			this.orphan = orphan;
1215
		}
1216

  
1217
		public void replace(CollectionPersister persister, Map copyCache) {
1218
			if ( addedValue != null ) {
1219
				addedValue = getReplacement( persister.getElementType(), addedValue, copyCache );
1220
			}
1221
		}
1222

  
1223
		protected final Object getReplacement(Type type, Object current, Map copyCache) {
1224
			return type.replace( current, null, session, owner, copyCache );
1225
		}
1226

  
1227
		@Override
1228
		public final Object getAddedInstance() {
1229
			return addedValue;
1230
		}
1231

  
1232
		@Override
1233
		public final Object getOrphan() {
1234
			return orphan;
1235
		}
1236
	}
1237

  
1202 1238
	/**
1203 1239
	 * Given a collection of entity instances that used to
1204 1240
	 * belong to the collection, and a collection of instances
......
1213 1249

  
1214 1250
		// short-circuit(s)
1215 1251
		if ( currentElements.size() == 0 ) {
1216
			return oldElements; // no new elements, the old list contains only Orphans
1252
			// no new elements, the old list contains only Orphans
1253
			return oldElements;
1217 1254
		}
1218 1255
		if ( oldElements.size() == 0 ) {
1219
			return oldElements; // no old elements, so no Orphans neither
1256
			// no old elements, so no Orphans neither
1257
			return oldElements;
1220 1258
		}
1221 1259

  
1222 1260
		final EntityPersister entityPersister = session.getFactory().getEntityPersister( entityName );
1223 1261
		final Type idType = entityPersister.getIdentifierType();
1262
		final boolean useIdDirect = mayUseIdDirect( idType );
1224 1263

  
1225 1264
		// create the collection holding the Orphans
1226
		Collection res = new ArrayList();
1265
		final Collection res = new ArrayList();
1227 1266

  
1228 1267
		// collect EntityIdentifier(s) of the *current* elements - add them into a HashSet for fast access
1229
		java.util.Set currentIds = new HashSet();
1230
		java.util.Set currentSaving = new IdentitySet();
1268
		final java.util.Set currentIds = new HashSet();
1269
		final java.util.Set currentSaving = new IdentitySet();
1231 1270
		for ( Object current : currentElements ) {
1232 1271
			if ( current != null && ForeignKeys.isNotTransient( entityName, current, null, session ) ) {
1233
				EntityEntry ee = session.getPersistenceContext().getEntry( current );
1272
				final EntityEntry ee = session.getPersistenceContext().getEntry( current );
1234 1273
				if ( ee != null && ee.getStatus() == Status.SAVING ) {
1235 1274
					currentSaving.add( current );
1236 1275
				}
1237 1276
				else {
1238
					Serializable currentId = ForeignKeys.getEntityIdentifierIfNotUnsaved(
1277
					final Serializable currentId = ForeignKeys.getEntityIdentifierIfNotUnsaved(
1239 1278
							entityName,
1240 1279
							current,
1241 1280
							session
1242 1281
					);
1243
					currentIds.add( new TypedValue( idType, currentId, entityPersister.getEntityMode() ) );
1282
					currentIds.add( useIdDirect ? currentId : new TypedValue( idType, currentId ) );
1244 1283
				}
1245 1284
			}
1246 1285
		}
......
1248 1287
		// iterate over the *old* list
1249 1288
		for ( Object old : oldElements ) {
1250 1289
			if ( !currentSaving.contains( old ) ) {
1251
				Serializable oldId = ForeignKeys.getEntityIdentifierIfNotUnsaved( entityName, old, session );
1252
				if ( !currentIds.contains( new TypedValue( idType, oldId, entityPersister.getEntityMode() ) ) ) {
1290
				final Serializable oldId = ForeignKeys.getEntityIdentifierIfNotUnsaved( entityName, old, session );
1291
				if ( !currentIds.contains( useIdDirect ? oldId : new TypedValue( idType, oldId ) ) ) {
1253 1292
					res.add( old );
1254 1293
				}
1255 1294
			}
......
1258 1297
		return res;
1259 1298
	}
1260 1299

  
1300
	private static boolean mayUseIdDirect(Type idType) {
1301
		return idType == StringType.INSTANCE
1302
			|| idType == IntegerType.INSTANCE
1303
			|| idType == LongType.INSTANCE
1304
			|| idType == UUIDBinaryType.INSTANCE
1305
			|| idType == UUIDCharType.INSTANCE
1306
			|| idType == PostgresUUIDType.INSTANCE;
1307
	}
1308

  
1309
	/**
1310
	 * Removes entity entries that have an equal identifier with the incoming entity instance
1311
	 *
1312
	 * @param list The list containing the entity instances
1313
	 * @param entityInstance The entity instance to match elements.
1314
	 * @param entityName The entity name
1315
	 * @param session The session
1316
	 */
1261 1317
	public static void identityRemove(
1262 1318
			Collection list,
1263
			Object object,
1319
			Object entityInstance,
1264 1320
			String entityName,
1265
			SessionImplementor session) throws HibernateException {
1321
			SessionImplementor session) {
1266 1322

  
1267
		if ( object != null && ForeignKeys.isNotTransient( entityName, object, null, session ) ) {
1323
		if ( entityInstance != null && ForeignKeys.isNotTransient( entityName, entityInstance, null, session ) ) {
1268 1324
			final EntityPersister entityPersister = session.getFactory().getEntityPersister( entityName );
1269
			Type idType = entityPersister.getIdentifierType();
1325
			final Type idType = entityPersister.getIdentifierType();
1270 1326

  
1271
			Serializable idOfCurrent = ForeignKeys.getEntityIdentifierIfNotUnsaved( entityName, object, session );
1272
			Iterator itr = list.iterator();
1327
			final Serializable idOfCurrent = ForeignKeys.getEntityIdentifierIfNotUnsaved( entityName, entityInstance, session );
1328
			final Iterator itr = list.iterator();
1273 1329
			while ( itr.hasNext() ) {
1274
				Serializable idOfOld = ForeignKeys.getEntityIdentifierIfNotUnsaved( entityName, itr.next(), session );
1330
				final Serializable idOfOld = ForeignKeys.getEntityIdentifierIfNotUnsaved( entityName, itr.next(), session );
1275 1331
				if ( idType.isEqual( idOfCurrent, idOfOld, session.getFactory() ) ) {
1276 1332
					itr.remove();
1277 1333
					break;
......
1282 1338
	}
1283 1339

  
1284 1340
	@Override
1285
    public Object getIdentifier(Object entry, int i) {
1341
	public Object getIdentifier(Object entry, int i) {
1286 1342
		throw new UnsupportedOperationException();
1287 1343
	}
1288 1344

  
1289 1345
	@Override
1290
    public Object getOwner() {
1346
	public Object getOwner() {
1291 1347
		return owner;
1292 1348
	}
1293 1349

  
1294 1350
	@Override
1295
    public void setOwner(Object owner) {
1351
	public void setOwner(Object owner) {
1296 1352
		this.owner = owner;
1297 1353
	}
1298 1354

  
1299
	/** ------ Below is section of code which makes remote service calls ----- */
1355
/** #################################################################### 
1356
    
1357
    ADDED PART: Below is section of code which makes remote service calls 
1358
    
1359
    #################################################################### */
1360
    
1361
	
1300 1362
	// The affected methods are :
1301 1363
	// initialize(final boolean writing)
1302 1364
	// readSize()
......
1320 1382
			try {
1321 1383
				String role = getRole();
1322 1384
				String fieldName = role.substring(role.lastIndexOf(".") + 1);
1323
				log.info("--> Remote Lazy Initializing Collection " + getRole() + " , owner : " + getOwner().getClass() + "/" + getKey() + " , field : " + fieldName);
1385
				LOG.info("--> Remote Lazy Initializing Collection " + getRole() + " , owner : " + getOwner().getClass() + "/" + getKey() + " , field : " + fieldName);
1324 1386
				Object owner = getOwner();
1325 1387
				CdmBase cdmBase;
1326 1388
				if(owner instanceof CdmBase) {
......
1359 1421
			}
1360 1422
		}
1361 1423
	}
1362

  
1363

  
1364

  
1365
}
1366

  
1424
}

Also available in: Unified diff

Add picture from clipboard (Maximum size: 40 MB)