Project

General

Profile

« Previous | Next » 

Revision 68144e34

Added by Andreas Müller over 3 years ago

ref #9204 revert changes to AbstractPersistentCollection, only keep new serialVersionUID (for doing it step by step)

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;
38 37

  
39 38
import javax.naming.NamingException;
40 39

  
41 40
import org.hibernate.AssertionFailure;
42
import org.hibernate.FlushMode;
43 41
import org.hibernate.HibernateException;
44 42
import org.hibernate.LazyInitializationException;
45 43
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;
51 44
import org.hibernate.collection.spi.PersistentCollection;
52 45
import org.hibernate.engine.internal.ForeignKeys;
53 46
import org.hibernate.engine.spi.CollectionEntry;
......
56 49
import org.hibernate.engine.spi.SessionImplementor;
57 50
import org.hibernate.engine.spi.Status;
58 51
import org.hibernate.engine.spi.TypedValue;
59
import org.hibernate.internal.CoreLogging;
60
import org.hibernate.internal.CoreMessageLogger;
61 52
import org.hibernate.internal.SessionFactoryRegistry;
62 53
import org.hibernate.internal.util.MarkerObject;
63 54
import org.hibernate.internal.util.collections.EmptyIterator;
......
65 56
import org.hibernate.persister.collection.CollectionPersister;
66 57
import org.hibernate.persister.entity.EntityPersister;
67 58
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;
73 59
import org.hibernate.type.Type;
74
import org.hibernate.type.UUIDBinaryType;
75
import org.hibernate.type.UUIDCharType;
76 60
import org.jboss.logging.Logger;
77 61

  
78 62
import eu.etaxonomy.cdm.api.application.CdmApplicationRemoteConfiguration;
......
92 76
 * @author Cherian Mathew
93 77
 */
94 78
public abstract class AbstractPersistentCollection implements Serializable, PersistentCollection {
95
	
79
	private static final Logger log = Logger.getLogger( AbstractPersistentCollection.class );
80

  
96 81
	/**
97 82
	 * <b>IMPORTANT:</b><br>
98 83
	 * This serialVersionUID must be kept in sync with the serialVersionUID which is generated
......
113 98
	 */
114 99
	private static final long serialVersionUID = 7094296207968006972L;
115 100

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

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

  
134 116
	private String sessionFactoryUuid;
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
	}
117
	private boolean specjLazyLoad = false;
147 118

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  
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

  
259
		if ( isTempSession ) {
260
			// TODO: On the next major release, add an
261
			// 'isJTA' or 'getTransactionFactory' method to Session.
262
			/*isJTA = session.getTransactionCoordinator()
263
					.getTransactionContext().getTransactionEnvironment()
264
					.getTransactionFactory()
265
					.compatibleWithJtaSynchronization();*/
291 266
			isJTA = session.getTransactionCoordinator().getTransactionCoordinatorBuilder().isJta();
292
			
293 267
			if ( !isJTA ) {
294 268
				// Explicitly handle the transactions only if we're not in
295 269
				// a JTA environment.  A lazy loading temporary session can
296 270
				// be created even if a current session and transaction are
297 271
				// open (ex: session.clear() was used).  We must prevent
298 272
				// multiple transactions.
299
				( (Session) session ).beginTransaction();
273
				( ( Session) session ).beginTransaction();
300 274
			}
301 275

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

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

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

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

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

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

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

  
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();
393
			} else {
394
				class ExtraLazyElementByIndexReader implements LazyInitializationWork {
395
					private boolean isExtraLazy;
396
					private Object element;
397

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

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

  
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;
432
	private boolean isConnectedToSession() {
433
		return session != null &&
434
				session.isOpen() &&
435
				session.getPersistenceContext().containsCollection( this );
448 436
	}
449 437

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

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

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

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

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

  
527 515
	/**
......
533 521
			operationQueue = new ArrayList<DelayedOperation>( 10 );
534 522
		}
535 523
		operationQueue.add( operation );
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
		}
524
		dirty = true; //needed so that we remove this collection from the second-level cache
552 525
	}
553 526

  
554 527
	/**
......
561 534
		}
562 535
	}
563 536

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  
707

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

  
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

  
746
	/**
747
	 * Do we need to completely recreate this collection when it changes?
748
	 */
758 749
	@Override
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
		}
750
    public boolean needsRecreate(CollectionPersister persister) {
782 751
		return false;
783 752
	}
784 753

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  
905 906
	}
906 907

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

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

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

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

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

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

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

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

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

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

  
963 965
	}
964 966

  
965 967
	protected class SetProxy implements java.util.Set {
......
970 972
		}
971 973

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

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

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

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

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

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

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

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

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

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

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

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

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

  
1048 1048
	}
1049 1049

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

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

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

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

  
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

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

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

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

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

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

  
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
	 */
1317 1260
	public static void identityRemove(
1318 1261
			Collection list,
1319
			Object entityInstance,
1262
			Object object,
1320 1263
			String entityName,
1321
			SessionImplementor session) {
1264
			SessionImplementor session) throws HibernateException {
1322 1265

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

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

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

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

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

  
......
1374 1317
		configuration = conf;
1375 1318
	}
1376 1319

  
1377

  
1378 1320
	private void remoteInitialize() {
1379 1321

  
1380 1322
		if (getOwner() != null && !initialized) {
......
1382 1324
			try {
1383 1325
				String role = getRole();
1384 1326
				String fieldName = role.substring(role.lastIndexOf(".") + 1);
1385
				LOG.info("--> Remote Lazy Initializing Collection " + getRole() + " , owner : " + getOwner().getClass() + "/" + getKey() + " , field : " + fieldName);
1327
				log.info("--> Remote Lazy Initializing Collection " + getRole() + " , owner : " + getOwner().getClass() + "/" + getKey() + " , field : " + fieldName);
1386 1328
				Object owner = getOwner();
1387 1329
				CdmBase cdmBase;
1388 1330
				if(owner instanceof CdmBase) {

Also available in: Unified diff