4 * Hibernate, Relational Persistence for Idiomatic Java
6 * Copyright (c) 2008-2011, Red Hat Inc. or third-party contributors as
7 * indicated by the @author tags or express copyright attribution
8 * statements applied by the authors. All third-party contributions are
9 * distributed under license by Red Hat Inc.
11 * This copyrighted material is made available to anyone wishing to use, modify,
12 * copy, or redistribute it subject to the terms and conditions of the GNU
13 * Lesser General Public License, as published by the Free Software Foundation.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
17 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
20 * You should have received a copy of the GNU Lesser General Public License
21 * along with this distribution; if not, write to:
22 * Free Software Foundation, Inc.
23 * 51 Franklin Street, Fifth Floor
24 * Boston, MA 02110-1301 USA
26 package org
.hibernate
.collection
.internal
;
28 import java
.io
.Serializable
;
29 import java
.util
.ArrayList
;
30 import java
.util
.Collection
;
31 import java
.util
.Collections
;
32 import java
.util
.HashSet
;
33 import java
.util
.Iterator
;
34 import java
.util
.List
;
35 import java
.util
.ListIterator
;
37 import javax
.naming
.NamingException
;
39 import org
.hibernate
.AssertionFailure
;
40 import org
.hibernate
.HibernateException
;
41 import org
.hibernate
.LazyInitializationException
;
42 import org
.hibernate
.Session
;
43 import org
.hibernate
.collection
.spi
.PersistentCollection
;
44 import org
.hibernate
.engine
.internal
.ForeignKeys
;
45 import org
.hibernate
.engine
.spi
.CollectionEntry
;
46 import org
.hibernate
.engine
.spi
.EntityEntry
;
47 import org
.hibernate
.engine
.spi
.SessionFactoryImplementor
;
48 import org
.hibernate
.engine
.spi
.SessionImplementor
;
49 import org
.hibernate
.engine
.spi
.Status
;
50 import org
.hibernate
.engine
.spi
.TypedValue
;
51 import org
.hibernate
.internal
.SessionFactoryRegistry
;
52 import org
.hibernate
.internal
.util
.MarkerObject
;
53 import org
.hibernate
.internal
.util
.collections
.EmptyIterator
;
54 import org
.hibernate
.internal
.util
.collections
.IdentitySet
;
55 import org
.hibernate
.persister
.collection
.CollectionPersister
;
56 import org
.hibernate
.persister
.entity
.EntityPersister
;
57 import org
.hibernate
.pretty
.MessageHelper
;
58 import org
.hibernate
.type
.Type
;
59 import org
.jboss
.logging
.Logger
;
62 * Base class implementing {@link org.hibernate.collection.spi.PersistentCollection}
66 public abstract class AbstractPersistentCollection
implements Serializable
, PersistentCollection
{
67 private static final Logger log
= Logger
.getLogger( AbstractPersistentCollection
.class );
69 private static final long serialVersionUID
= -7238232378593030571L;
71 private transient SessionImplementor session
;
72 private boolean initialized
;
73 private transient List
<DelayedOperation
> operationQueue
;
74 private transient boolean directlyAccessible
;
75 private transient boolean initializing
;
77 private int cachedSize
= -1;
80 private Serializable key
;
81 // collections detect changes made via their public interface and mark
82 // themselves as dirty as a performance optimization
83 private boolean dirty
;
84 private Serializable storedSnapshot
;
86 private String sessionFactoryUuid
;
87 private boolean specjLazyLoad
= false;
89 public final String
getRole() {
93 public final Serializable
getKey() {
97 public final boolean isUnreferenced() {
101 public final boolean isDirty() {
105 public final void clearDirty() {
109 public final void dirty() {
113 public final Serializable
getStoredSnapshot() {
114 return storedSnapshot
;
117 //Careful: these methods do not initialize the collection.
120 * Is the initialized collection empty?
122 public abstract boolean empty();
125 * Called by any read-only method of the collection interface
127 protected final void read() {
132 * Called by the {@link Collection#size} method
134 @SuppressWarnings({"JavaDoc"})
135 protected boolean readSize() {
136 if ( !initialized
) {
137 if ( cachedSize
!= -1 && !hasQueuedOperations() ) {
141 boolean isExtraLazy
= withTemporarySessionIfNeeded(
142 new LazyInitializationWork
<Boolean
>() {
144 public Boolean
doWork() {
145 CollectionEntry entry
= session
.getPersistenceContext().getCollectionEntry( AbstractPersistentCollection
.this );
147 if ( entry
!= null ) {
148 CollectionPersister persister
= entry
.getLoadedPersister();
149 if ( persister
.isExtraLazy() ) {
150 if ( hasQueuedOperations() ) {
153 cachedSize
= persister
.getSize( entry
.getLoadedKey(), session
);
161 throwLazyInitializationExceptionIfNotConnected();
175 public static interface LazyInitializationWork
<T
> {
179 private <T
> T
withTemporarySessionIfNeeded(LazyInitializationWork
<T
> lazyInitializationWork
) {
180 SessionImplementor originalSession
= null;
181 boolean isTempSession
= false;
182 boolean isJTA
= false;
184 if ( session
== null ) {
185 if ( specjLazyLoad
) {
186 session
= openTemporarySessionForLoading();
187 isTempSession
= true;
190 throwLazyInitializationException( "could not initialize proxy - no Session" );
193 else if ( !session
.isOpen() ) {
194 if ( specjLazyLoad
) {
195 originalSession
= session
;
196 session
= openTemporarySessionForLoading();
197 isTempSession
= true;
200 throwLazyInitializationException( "could not initialize proxy - the owning Session was closed" );
203 else if ( !session
.isConnected() ) {
204 if ( specjLazyLoad
) {
205 originalSession
= session
;
206 session
= openTemporarySessionForLoading();
207 isTempSession
= true;
210 throwLazyInitializationException( "could not initialize proxy - the owning Session is disconnected" );
214 if ( isTempSession
) {
215 // TODO: On the next major release, add an
216 // 'isJTA' or 'getTransactionFactory' method to Session.
217 isJTA
= session
.getTransactionCoordinator()
218 .getTransactionContext().getTransactionEnvironment()
219 .getTransactionFactory()
220 .compatibleWithJtaSynchronization();
223 // Explicitly handle the transactions only if we're not in
224 // a JTA environment. A lazy loading temporary session can
225 // be created even if a current session and transaction are
226 // open (ex: session.clear() was used). We must prevent
227 // multiple transactions.
228 ( ( Session
) session
).beginTransaction();
231 session
.getPersistenceContext().addUninitializedDetachedCollection(
232 session
.getFactory().getCollectionPersister( getRole() ),
238 return lazyInitializationWork
.doWork();
241 if ( isTempSession
) {
242 // make sure the just opened temp session gets closed!
245 ( ( Session
) session
).getTransaction().commit();
247 ( (Session
) session
).close();
249 catch (Exception e
) {
250 log
.warn( "Unable to close temporary session used to load lazy collection associated to no session" );
252 session
= originalSession
;
257 private SessionImplementor
openTemporarySessionForLoading() {
258 if ( sessionFactoryUuid
== null ) {
259 throwLazyInitializationException( "SessionFactory UUID not known to create temporary Session for loading" );
262 SessionFactoryImplementor sf
= (SessionFactoryImplementor
)
263 SessionFactoryRegistry
.INSTANCE
.getSessionFactory( sessionFactoryUuid
);
264 return (SessionImplementor
) sf
.openSession();
267 protected Boolean
readIndexExistence(final Object index
) {
268 if ( !initialized
) {
269 Boolean extraLazyExistenceCheck
= withTemporarySessionIfNeeded(
270 new LazyInitializationWork
<Boolean
>() {
272 public Boolean
doWork() {
273 CollectionEntry entry
= session
.getPersistenceContext().getCollectionEntry( AbstractPersistentCollection
.this );
274 CollectionPersister persister
= entry
.getLoadedPersister();
275 if ( persister
.isExtraLazy() ) {
276 if ( hasQueuedOperations() ) {
279 return persister
.indexExists( entry
.getLoadedKey(), index
, session
);
288 if ( extraLazyExistenceCheck
!= null ) {
289 return extraLazyExistenceCheck
;
295 protected Boolean
readElementExistence(final Object element
) {
296 if ( !initialized
) {
297 Boolean extraLazyExistenceCheck
= withTemporarySessionIfNeeded(
298 new LazyInitializationWork
<Boolean
>() {
300 public Boolean
doWork() {
301 CollectionEntry entry
= session
.getPersistenceContext().getCollectionEntry( AbstractPersistentCollection
.this );
302 CollectionPersister persister
= entry
.getLoadedPersister();
303 if ( persister
.isExtraLazy() ) {
304 if ( hasQueuedOperations() ) {
307 return persister
.elementExists( entry
.getLoadedKey(), element
, session
);
316 if ( extraLazyExistenceCheck
!= null ) {
317 return extraLazyExistenceCheck
;
323 protected static final Object UNKNOWN
= new MarkerObject( "UNKNOWN" );
325 protected Object
readElementByIndex(final Object index
) {
326 if ( !initialized
) {
327 class ExtraLazyElementByIndexReader
implements LazyInitializationWork
{
328 private boolean isExtraLazy
;
329 private Object element
;
332 public Object
doWork() {
333 CollectionEntry entry
= session
.getPersistenceContext().getCollectionEntry( AbstractPersistentCollection
.this );
334 CollectionPersister persister
= entry
.getLoadedPersister();
335 isExtraLazy
= persister
.isExtraLazy();
337 if ( hasQueuedOperations() ) {
340 element
= persister
.getElementByIndex( entry
.getLoadedKey(), index
, session
, owner
);
349 ExtraLazyElementByIndexReader reader
= new ExtraLazyElementByIndexReader();
350 //noinspection unchecked
351 withTemporarySessionIfNeeded( reader
);
352 if ( reader
.isExtraLazy
) {
353 return reader
.element
;
360 protected int getCachedSize() {
364 private boolean isConnectedToSession() {
365 return session
!= null &&
367 session
.getPersistenceContext().containsCollection( this );
371 * Called by any writer method of the collection interface
373 protected final void write() {
379 * Is this collection in a state that would allow us to
380 * "queue" operations?
382 @SuppressWarnings({"JavaDoc"})
383 protected boolean isOperationQueueEnabled() {
384 return !initialized
&&
385 isConnectedToSession() &&
386 isInverseCollection();
390 * Is this collection in a state that would allow us to
391 * "queue" puts? This is a special case, because of orphan
394 @SuppressWarnings({"JavaDoc"})
395 protected boolean isPutQueueEnabled() {
396 return !initialized
&&
397 isConnectedToSession() &&
398 isInverseOneToManyOrNoOrphanDelete();
402 * Is this collection in a state that would allow us to
403 * "queue" clear? This is a special case, because of orphan
406 @SuppressWarnings({"JavaDoc"})
407 protected boolean isClearQueueEnabled() {
408 return !initialized
&&
409 isConnectedToSession() &&
410 isInverseCollectionNoOrphanDelete();
414 * Is this the "inverse" end of a bidirectional association?
416 @SuppressWarnings({"JavaDoc"})
417 private boolean isInverseCollection() {
418 CollectionEntry ce
= session
.getPersistenceContext().getCollectionEntry( this );
419 return ce
!= null && ce
.getLoadedPersister().isInverse();
423 * Is this the "inverse" end of a bidirectional association with
424 * no orphan delete enabled?
426 @SuppressWarnings({"JavaDoc"})
427 private boolean isInverseCollectionNoOrphanDelete() {
428 CollectionEntry ce
= session
.getPersistenceContext().getCollectionEntry( this );
430 ce
.getLoadedPersister().isInverse() &&
431 !ce
.getLoadedPersister().hasOrphanDelete();
435 * Is this the "inverse" end of a bidirectional one-to-many, or
436 * of a collection with no orphan delete?
438 @SuppressWarnings({"JavaDoc"})
439 private boolean isInverseOneToManyOrNoOrphanDelete() {
440 CollectionEntry ce
= session
.getPersistenceContext().getCollectionEntry( this );
441 return ce
!= null && ce
.getLoadedPersister().isInverse() && (
442 ce
.getLoadedPersister().isOneToMany() ||
443 !ce
.getLoadedPersister().hasOrphanDelete()
450 @SuppressWarnings({"JavaDoc"})
451 protected final void queueOperation(DelayedOperation operation
) {
452 if ( operationQueue
== null ) {
453 operationQueue
= new ArrayList
<DelayedOperation
>( 10 );
455 operationQueue
.add( operation
);
456 dirty
= true; //needed so that we remove this collection from the second-level cache
460 * After reading all existing elements from the database,
461 * add the queued elements to the underlying collection.
463 protected final void performQueuedOperations() {
464 for ( DelayedOperation operation
: operationQueue
) {
470 * After flushing, re-init snapshot state.
472 public void setSnapshot(Serializable key
, String role
, Serializable snapshot
) {
475 this.storedSnapshot
= snapshot
;
479 * After flushing, clear any "queued" additions, since the
480 * database state is now synchronized with the memory state.
482 public void postAction() {
483 operationQueue
= null;
489 * Not called by Hibernate, but used by non-JDK serialization,
490 * eg. SOAP libraries.
492 public AbstractPersistentCollection() {
495 protected AbstractPersistentCollection(SessionImplementor session
) {
496 this.session
= session
;
500 * return the user-visible collection (or array) instance
502 public Object
getValue() {
507 * Called just before reading any rows from the JDBC result set
509 public void beginRead() {
510 // override on some subclasses
515 * Called after reading all rows from the JDBC result set
517 public boolean endRead() {
518 //override on some subclasses
519 return afterInitialize();
522 public boolean afterInitialize() {
524 //do this bit after setting initialized to true or it will recurse
525 if ( operationQueue
!= null ) {
526 performQueuedOperations();
527 operationQueue
= null;
537 * Initialize the collection, if possible, wrapping any exceptions
538 * in a runtime exception
540 * @param writing currently obsolete
542 * @throws LazyInitializationException if we cannot initialize
544 protected final void initialize(final boolean writing
) {
549 withTemporarySessionIfNeeded(
550 new LazyInitializationWork
<Object
>() {
552 public Object
doWork() {
553 session
.initializeCollection( AbstractPersistentCollection
.this, writing
);
560 private void throwLazyInitializationExceptionIfNotConnected() {
561 if ( !isConnectedToSession() ) {
562 throwLazyInitializationException( "no session or session was closed" );
564 if ( !session
.isConnected() ) {
565 throwLazyInitializationException( "session is disconnected" );
569 private void throwLazyInitializationException(String message
) {
570 throw new LazyInitializationException(
571 "failed to lazily initialize a collection" +
572 (role
== null ?
"" : " of role: " + role
) +
577 protected final void setInitialized() {
578 this.initializing
= false;
579 this.initialized
= true;
582 protected final void setDirectlyAccessible(boolean directlyAccessible
) {
583 this.directlyAccessible
= directlyAccessible
;
587 * Could the application possibly have a direct reference to
588 * the underlying collection implementation?
590 public boolean isDirectlyAccessible() {
591 return directlyAccessible
;
595 * Disassociate this collection from the given session.
597 * @return true if this was currently associated with the given session
599 public final boolean unsetSession(SessionImplementor currentSession
) {
600 prepareForPossibleSpecialSpecjInitialization();
601 if ( currentSession
== this.session
) {
610 protected void prepareForPossibleSpecialSpecjInitialization() {
611 if ( session
!= null ) {
612 specjLazyLoad
= session
.getFactory().getSettings().isInitializeLazyStateOutsideTransactionsEnabled();
614 if ( specjLazyLoad
&& sessionFactoryUuid
== null ) {
616 sessionFactoryUuid
= (String
) session
.getFactory().getReference().get( "uuid" ).getContent();
618 catch (NamingException e
) {
619 //not much we can do if this fails...
627 * Associate the collection with the given session.
629 * @return false if the collection was already associated with the session
631 * @throws HibernateException if the collection was already associated
632 * with another open session
634 public final boolean setCurrentSession(SessionImplementor session
) throws HibernateException
{
635 if ( session
== this.session
) {
639 if ( isConnectedToSession() ) {
640 CollectionEntry ce
= session
.getPersistenceContext().getCollectionEntry( this );
642 throw new HibernateException(
643 "Illegal attempt to associate a collection with two open sessions"
647 throw new HibernateException(
648 "Illegal attempt to associate a collection with two open sessions: " +
649 MessageHelper
.collectionInfoString(
650 ce
.getLoadedPersister(), this,
651 ce
.getLoadedKey(), session
657 this.session
= session
;
664 * Do we need to completely recreate this collection when it changes?
666 public boolean needsRecreate(CollectionPersister persister
) {
671 * To be called internally by the session, forcing
672 * immediate initialization.
674 public final void forceInitialization() throws HibernateException
{
675 if ( !initialized
) {
676 if ( initializing
) {
677 throw new AssertionFailure( "force initialize loading collection" );
679 if ( session
== null ) {
680 throw new HibernateException( "collection is not associated with any session" );
682 if ( !session
.isConnected() ) {
683 throw new HibernateException( "disconnected session" );
685 session
.initializeCollection( this, false );
691 * Get the current snapshot from the session
693 @SuppressWarnings({"JavaDoc"})
694 protected final Serializable
getSnapshot() {
695 return session
.getPersistenceContext().getSnapshot( this );
699 * Is this instance initialized?
701 public final boolean wasInitialized() {
705 public boolean isRowUpdatePossible() {
710 * Does this instance have any "queued" additions?
712 public final boolean hasQueuedOperations() {
713 return operationQueue
!= null;
717 * Iterate the "queued" additions
719 public final Iterator
queuedAdditionIterator() {
720 if ( hasQueuedOperations() ) {
721 return new Iterator() {
724 public Object
next() {
725 return operationQueue
.get( i
++ ).getAddedInstance();
728 public boolean hasNext() {
729 return i
< operationQueue
.size();
732 public void remove() {
733 throw new UnsupportedOperationException();
738 return EmptyIterator
.INSTANCE
;
743 * Iterate the "queued" additions
745 @SuppressWarnings({"unchecked"})
746 public final Collection
getQueuedOrphans(String entityName
) {
747 if ( hasQueuedOperations() ) {
748 Collection additions
= new ArrayList( operationQueue
.size() );
749 Collection removals
= new ArrayList( operationQueue
.size() );
750 for ( DelayedOperation operation
: operationQueue
) {
751 additions
.add( operation
.getAddedInstance() );
752 removals
.add( operation
.getOrphan() );
754 return getOrphans( removals
, additions
, entityName
, session
);
757 return Collections
.EMPTY_LIST
;
762 * Called before inserting rows, to ensure that any surrogate keys
763 * are fully generated
765 public void preInsert(CollectionPersister persister
) throws HibernateException
{
769 * Called after inserting a row, to fetch the natively generated id
771 public void afterRowInsert(CollectionPersister persister
, Object entry
, int i
) throws HibernateException
{
775 * get all "orphaned" elements
777 public abstract Collection
getOrphans(Serializable snapshot
, String entityName
) throws HibernateException
;
780 * Get the current session
782 @SuppressWarnings({"JavaDoc"})
783 public final SessionImplementor
getSession() {
787 protected final class IteratorProxy
implements Iterator
{
788 protected final Iterator itr
;
790 public IteratorProxy(Iterator itr
) {
794 public boolean hasNext() {
795 return itr
.hasNext();
798 public Object
next() {
802 public void remove() {
809 protected final class ListIteratorProxy
implements ListIterator
{
810 protected final ListIterator itr
;
812 public ListIteratorProxy(ListIterator itr
) {
816 @SuppressWarnings({"unchecked"})
817 public void add(Object o
) {
822 public boolean hasNext() {
823 return itr
.hasNext();
826 public boolean hasPrevious() {
827 return itr
.hasPrevious();
830 public Object
next() {
834 public int nextIndex() {
835 return itr
.nextIndex();
838 public Object
previous() {
839 return itr
.previous();
842 public int previousIndex() {
843 return itr
.previousIndex();
846 public void remove() {
851 @SuppressWarnings({"unchecked"})
852 public void set(Object o
) {
859 protected class SetProxy
implements java
.util
.Set
{
860 protected final Collection set
;
862 public SetProxy(Collection set
) {
866 @SuppressWarnings({"unchecked"})
867 public boolean add(Object o
) {
872 @SuppressWarnings({"unchecked"})
873 public boolean addAll(Collection c
) {
875 return set
.addAll( c
);
878 public void clear() {
883 public boolean contains(Object o
) {
884 return set
.contains( o
);
887 public boolean containsAll(Collection c
) {
888 return set
.containsAll( c
);
891 public boolean isEmpty() {
892 return set
.isEmpty();
895 public Iterator
iterator() {
896 return new IteratorProxy( set
.iterator() );
899 public boolean remove(Object o
) {
901 return set
.remove( o
);
904 public boolean removeAll(Collection c
) {
906 return set
.removeAll( c
);
909 public boolean retainAll(Collection c
) {
911 return set
.retainAll( c
);
918 public Object
[] toArray() {
919 return set
.toArray();
922 @SuppressWarnings({"unchecked"})
923 public Object
[] toArray(Object
[] array
) {
924 return set
.toArray( array
);
929 protected final class ListProxy
implements java
.util
.List
{
930 protected final List list
;
932 public ListProxy(List list
) {
937 @SuppressWarnings({"unchecked"})
938 public void add(int index
, Object value
) {
940 list
.add( index
, value
);
944 @SuppressWarnings({"unchecked"})
945 public boolean add(Object o
) {
947 return list
.add( o
);
951 @SuppressWarnings({"unchecked"})
952 public boolean addAll(Collection c
) {
954 return list
.addAll( c
);
958 @SuppressWarnings({"unchecked"})
959 public boolean addAll(int i
, Collection c
) {
961 return list
.addAll( i
, c
);
965 public void clear() {
971 public boolean contains(Object o
) {
972 return list
.contains( o
);
976 public boolean containsAll(Collection c
) {
977 return list
.containsAll( c
);
981 public Object
get(int i
) {
982 return list
.get( i
);
986 public int indexOf(Object o
) {
987 return list
.indexOf( o
);
991 public boolean isEmpty() {
992 return list
.isEmpty();
996 public Iterator
iterator() {
997 return new IteratorProxy( list
.iterator() );
1001 public int lastIndexOf(Object o
) {
1002 return list
.lastIndexOf( o
);
1006 public ListIterator
listIterator() {
1007 return new ListIteratorProxy( list
.listIterator() );
1011 public ListIterator
listIterator(int i
) {
1012 return new ListIteratorProxy( list
.listIterator( i
) );
1016 public Object
remove(int i
) {
1018 return list
.remove( i
);
1022 public boolean remove(Object o
) {
1024 return list
.remove( o
);
1028 public boolean removeAll(Collection c
) {
1030 return list
.removeAll( c
);
1034 public boolean retainAll(Collection c
) {
1036 return list
.retainAll( c
);
1040 @SuppressWarnings({"unchecked"})
1041 public Object
set(int i
, Object o
) {
1043 return list
.set( i
, o
);
1052 public List
subList(int i
, int j
) {
1053 return list
.subList( i
, j
);
1057 public Object
[] toArray() {
1058 return list
.toArray();
1062 @SuppressWarnings({"unchecked"})
1063 public Object
[] toArray(Object
[] array
) {
1064 return list
.toArray( array
);
1070 * Contract for operations which are part of a collection's operation queue.
1072 protected interface DelayedOperation
{
1073 public void operate();
1075 public Object
getAddedInstance();
1077 public Object
getOrphan();
1081 * Given a collection of entity instances that used to
1082 * belong to the collection, and a collection of instances
1083 * that currently belong, return a collection of orphans
1085 @SuppressWarnings({"JavaDoc", "unchecked"})
1086 protected static Collection
getOrphans(
1087 Collection oldElements
,
1088 Collection currentElements
,
1090 SessionImplementor session
) throws HibernateException
{
1093 if ( currentElements
.size() == 0 ) {
1094 return oldElements
; // no new elements, the old list contains only Orphans
1096 if ( oldElements
.size() == 0 ) {
1097 return oldElements
; // no old elements, so no Orphans neither
1100 final EntityPersister entityPersister
= session
.getFactory().getEntityPersister( entityName
);
1101 final Type idType
= entityPersister
.getIdentifierType();
1103 // create the collection holding the Orphans
1104 Collection res
= new ArrayList();
1106 // collect EntityIdentifier(s) of the *current* elements - add them into a HashSet for fast access
1107 java
.util
.Set currentIds
= new HashSet();
1108 java
.util
.Set currentSaving
= new IdentitySet();
1109 for ( Object current
: currentElements
) {
1110 if ( current
!= null && ForeignKeys
.isNotTransient( entityName
, current
, null, session
) ) {
1111 EntityEntry ee
= session
.getPersistenceContext().getEntry( current
);
1112 if ( ee
!= null && ee
.getStatus() == Status
.SAVING
) {
1113 currentSaving
.add( current
);
1116 Serializable currentId
= ForeignKeys
.getEntityIdentifierIfNotUnsaved(
1121 currentIds
.add( new TypedValue( idType
, currentId
, entityPersister
.getEntityMode() ) );
1126 // iterate over the *old* list
1127 for ( Object old
: oldElements
) {
1128 if ( !currentSaving
.contains( old
) ) {
1129 Serializable oldId
= ForeignKeys
.getEntityIdentifierIfNotUnsaved( entityName
, old
, session
);
1130 if ( !currentIds
.contains( new TypedValue( idType
, oldId
, entityPersister
.getEntityMode() ) ) ) {
1139 public static void identityRemove(
1143 SessionImplementor session
) throws HibernateException
{
1145 if ( object
!= null && ForeignKeys
.isNotTransient( entityName
, object
, null, session
) ) {
1146 final EntityPersister entityPersister
= session
.getFactory().getEntityPersister( entityName
);
1147 Type idType
= entityPersister
.getIdentifierType();
1149 Serializable idOfCurrent
= ForeignKeys
.getEntityIdentifierIfNotUnsaved( entityName
, object
, session
);
1150 Iterator itr
= list
.iterator();
1151 while ( itr
.hasNext() ) {
1152 Serializable idOfOld
= ForeignKeys
.getEntityIdentifierIfNotUnsaved( entityName
, itr
.next(), session
);
1153 if ( idType
.isEqual( idOfCurrent
, idOfOld
, session
.getFactory() ) ) {
1162 public Object
getIdentifier(Object entry
, int i
) {
1163 throw new UnsupportedOperationException();
1166 public Object
getOwner() {
1170 public void setOwner(Object owner
) {