import java.util.Map;
import org.hibernate.AssertionFailure;
+import org.hibernate.FlushMode;
import org.hibernate.HibernateException;
import org.hibernate.LazyInitializationException;
import org.hibernate.Session;
import org.hibernate.engine.internal.ForeignKeys;
import org.hibernate.engine.spi.CollectionEntry;
import org.hibernate.engine.spi.EntityEntry;
+import org.hibernate.engine.spi.PersistenceContext;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.engine.spi.SessionImplementor;
+import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.engine.spi.Status;
import org.hibernate.engine.spi.TypedValue;
import org.hibernate.internal.CoreLogging;
import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.internal.SessionFactoryRegistry;
import org.hibernate.internal.util.MarkerObject;
-import org.hibernate.internal.util.collections.EmptyIterator;
import org.hibernate.internal.util.collections.IdentitySet;
import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.pretty.MessageHelper;
+import org.hibernate.resource.transaction.spi.TransactionStatus;
import org.hibernate.type.CompositeType;
import org.hibernate.type.IntegerType;
import org.hibernate.type.LongType;
*/
private static final long serialVersionUID = 7094296207968006972L;
- private transient SessionImplementor session;
+ private transient SharedSessionContractImplementor session;
private boolean isTempSession = false;
private boolean initialized;
private transient List<DelayedOperation> operationQueue;
// collections detect changes made via their public interface and mark
// themselves as dirty as a performance optimization
private boolean dirty;
+ protected boolean elementRemoved;
private Serializable storedSnapshot;
private String sessionFactoryUuid;
public AbstractPersistentCollection() {
}
- protected AbstractPersistentCollection(SessionImplementor session) {
+ protected AbstractPersistentCollection(SharedSessionContractImplementor session) {
this.session = session;
}
+ /**
+ * @deprecated {@link #AbstractPersistentCollection(SharedSessionContractImplementor)} should be used instead.
+ */
+ @Deprecated
+ protected AbstractPersistentCollection(SessionImplementor session) {
+ this( (SharedSessionContractImplementor) session );
+ }
+
@Override
public final String getRole() {
return role;
return dirty;
}
+ @Override
+ public boolean isElementRemoved() {
+ return elementRemoved;
+ }
+
@Override
public final void clearDirty() {
dirty = false;
+ elementRemoved = false;
}
@Override
new LazyInitializationWork<Boolean>() {
@Override
public Boolean doWork() {
- final CollectionEntry entry = session.getPersistenceContext().getCollectionEntry( AbstractPersistentCollection.this );
+ final CollectionEntry entry = session.getPersistenceContextInternal().getCollectionEntry( AbstractPersistentCollection.this );
if ( entry != null ) {
final CollectionPersister persister = entry.getLoadedPersister();
}
private <T> T withTemporarySessionIfNeeded(LazyInitializationWork<T> lazyInitializationWork) {
- SessionImplementor tempSession = null;
+ SharedSessionContractImplementor tempSession = null;
if ( session == null ) {
if ( allowLoadOutsideTransaction ) {
throwLazyInitializationException( "could not initialize proxy - no Session" );
}
}
- else if ( !session.isOpen() ) {
+ else if ( !session.isOpenOrWaitingForAutoClose() ) {
if ( allowLoadOutsideTransaction ) {
tempSession = openTemporarySessionForLoading();
}
}
}
-
- SessionImplementor originalSession = null;
+ SharedSessionContractImplementor originalSession = null;
boolean isJTA = false;
if ( tempSession != null ) {
originalSession = session;
session = tempSession;
-
isJTA = session.getTransactionCoordinator().getTransactionCoordinatorBuilder().isJta();
if ( !isJTA ) {
( (Session) session ).beginTransaction();
}
- session.getPersistenceContext().addUninitializedDetachedCollection(
+ session.getPersistenceContextInternal().addUninitializedDetachedCollection(
session.getFactory().getCollectionPersister( getRole() ),
this
);
}
}
- private SessionImplementor openTemporarySessionForLoading() {
+ private SharedSessionContractImplementor openTemporarySessionForLoading() {
if ( sessionFactoryUuid == null ) {
throwLazyInitializationException( "SessionFactory UUID not known to create temporary Session for loading" );
}
final SessionFactoryImplementor sf = (SessionFactoryImplementor)
SessionFactoryRegistry.INSTANCE.getSessionFactory( sessionFactoryUuid );
- return (SessionImplementor) sf.openSession();
+ final SharedSessionContractImplementor session = (SharedSessionContractImplementor) sf.openSession();
+ session.getPersistenceContextInternal().setDefaultReadOnly( true );
+ session.setFlushMode( FlushMode.MANUAL );
+ return session;
}
protected Boolean readIndexExistence(final Object index) {
new LazyInitializationWork<Boolean>() {
@Override
public Boolean doWork() {
- final CollectionEntry entry = session.getPersistenceContext().getCollectionEntry( AbstractPersistentCollection.this );
+ final CollectionEntry entry = session.getPersistenceContextInternal().getCollectionEntry( AbstractPersistentCollection.this );
final CollectionPersister persister = entry.getLoadedPersister();
if ( persister.isExtraLazy() ) {
if ( hasQueuedOperations() ) {
new LazyInitializationWork<Boolean>() {
@Override
public Boolean doWork() {
- final CollectionEntry entry = session.getPersistenceContext().getCollectionEntry( AbstractPersistentCollection.this );
+ final CollectionEntry entry = session.getPersistenceContextInternal().getCollectionEntry( AbstractPersistentCollection.this );
final CollectionPersister persister = entry.getLoadedPersister();
if ( persister.isExtraLazy() ) {
if ( hasQueuedOperations() ) {
@Override
public Object doWork() {
- final CollectionEntry entry = session.getPersistenceContext().getCollectionEntry( AbstractPersistentCollection.this );
+ final CollectionEntry entry = session.getPersistenceContextInternal().getCollectionEntry( AbstractPersistentCollection.this );
final CollectionPersister persister = entry.getLoadedPersister();
isExtraLazy = persister.isExtraLazy();
if ( isExtraLazy ) {
protected boolean isConnectedToSession() {
return session != null
&& session.isOpen()
- && session.getPersistenceContext().containsCollection( this );
+ && session.getPersistenceContextInternal().containsCollection( this );
}
protected boolean isInitialized() {
*/
@SuppressWarnings({"JavaDoc"})
protected boolean isInverseCollection() {
- final CollectionEntry ce = session.getPersistenceContext().getCollectionEntry( this );
+ final CollectionEntry ce = session.getPersistenceContextInternal().getCollectionEntry( this );
return ce != null && ce.getLoadedPersister().isInverse();
}
*/
@SuppressWarnings({"JavaDoc"})
protected boolean isInverseCollectionNoOrphanDelete() {
- final CollectionEntry ce = session.getPersistenceContext().getCollectionEntry( this );
- return ce != null
- &&
- ce.getLoadedPersister().isInverse() &&
- !ce.getLoadedPersister().hasOrphanDelete();
+ final CollectionEntry ce = session.getPersistenceContextInternal().getCollectionEntry( this );
+ if ( ce == null ) {
+ return false;
+ }
+ final CollectionPersister loadedPersister = ce.getLoadedPersister();
+ return loadedPersister.isInverse() && !loadedPersister.hasOrphanDelete();
}
/**
*/
@SuppressWarnings({"JavaDoc"})
protected boolean isInverseOneToManyOrNoOrphanDelete() {
- final CollectionEntry ce = session.getPersistenceContext().getCollectionEntry( this );
- return ce != null
- && ce.getLoadedPersister().isInverse()
- && ( ce.getLoadedPersister().isOneToMany() || !ce.getLoadedPersister().hasOrphanDelete() );
+ final CollectionEntry ce = session.getPersistenceContextInternal().getCollectionEntry( this );
+ if ( ce == null ) {
+ return false;
+ }
+ final CollectionPersister loadedPersister = ce.getLoadedPersister();
+ return loadedPersister.isInverse() && ( loadedPersister.isOneToMany() || !loadedPersister.hasOrphanDelete() );
}
/**
for ( DelayedOperation operation : operationQueue ) {
operation.operate();
}
+ clearOperationQueue();
}
@Override
@Override
public void postAction() {
- operationQueue = null;
+ clearOperationQueue();
cachedSize = -1;
clearDirty();
}
+ public final void clearOperationQueue() {
+ operationQueue = null;
+ }
+
@Override
public Object getValue() {
return this;
public boolean afterInitialize() {
setInitialized();
//do this bit after setting initialized to true or it will recurse
- if ( operationQueue != null ) {
+ if ( hasQueuedOperations() ) {
performQueuedOperations();
- operationQueue = null;
cachedSize = -1;
return false;
}
}
@Override
- public final boolean unsetSession(SessionImplementor currentSession) {
+ public final boolean unsetSession(SharedSessionContractImplementor currentSession) {
prepareForPossibleLoadingOutsideTransaction();
if ( currentSession == this.session ) {
if ( !isTempSession ) {
+ if ( hasQueuedOperations() ) {
+ final String collectionInfoString = MessageHelper.collectionInfoString( getRole(), getKey() );
+ try {
+ final TransactionStatus transactionStatus =
+ session.getTransactionCoordinator().getTransactionDriverControl().getStatus();
+ if ( transactionStatus.isOneOf(
+ TransactionStatus.ROLLED_BACK,
+ TransactionStatus.MARKED_ROLLBACK,
+ TransactionStatus.FAILED_COMMIT,
+ TransactionStatus.FAILED_ROLLBACK,
+ TransactionStatus.ROLLING_BACK
+ ) ) {
+ // It was due to a rollback.
+ LOG.queuedOperationWhenDetachFromSessionOnRollback( collectionInfoString );
+ }
+ else {
+ // We don't know why the collection is being detached.
+ // Just log the info.
+ LOG.queuedOperationWhenDetachFromSession( collectionInfoString );
+ }
+ }
+ catch (Exception e) {
+ // We don't know why the collection is being detached.
+ // Just log the info.
+ LOG.queuedOperationWhenDetachFromSession( collectionInfoString );
+ }
+ }
+ if ( allowLoadOutsideTransaction && !initialized && session.getLoadQueryInfluencers().hasEnabledFilters() ) {
+ final String collectionInfoString = MessageHelper.collectionInfoString( getRole(), getKey() );
+ LOG.enabledFiltersWhenDetachFromSession( collectionInfoString );
+ }
this.session = null;
}
return true;
}
@Override
- public final boolean setCurrentSession(SessionImplementor session) throws HibernateException {
+ public final boolean setCurrentSession(SharedSessionContractImplementor session) throws HibernateException {
if ( session == this.session ) {
return false;
}
- else {
- if ( this.session != null ) {
- final String msg = generateUnexpectedSessionStateMessage( session );
- if ( isConnectedToSession() ) {
- throw new HibernateException(
- "Illegal attempt to associate a collection with two open sessions. " + msg
- );
- }
- else {
- LOG.logUnexpectedSessionInCollectionNotConnected( msg );
- this.session = session;
- return true;
- }
+ else if ( this.session != null ) {
+ final String msg = generateUnexpectedSessionStateMessage( session );
+ if ( isConnectedToSession() ) {
+ throw new HibernateException(
+ "Illegal attempt to associate a collection with two open sessions. " + msg
+ );
}
else {
- this.session = session;
- return true;
+ LOG.logUnexpectedSessionInCollectionNotConnected( msg );
}
}
+ if ( hasQueuedOperations() ) {
+ LOG.queuedOperationWhenAttachToSession( MessageHelper.collectionInfoString( getRole(), getKey() ) );
+ }
+ this.session = session;
+ return true;
}
- private String generateUnexpectedSessionStateMessage(SessionImplementor session) {
+ private String generateUnexpectedSessionStateMessage(SharedSessionContractImplementor session) {
// NOTE: If this.session != null, this.session may be operating on this collection
// (e.g., by changing this.role, this.key, or even this.session) in a different thread.
sb.append( MessageHelper.collectionInfoString( roleCurrent, keyCurrent ) );
}
else {
- final CollectionEntry ce = session.getPersistenceContext().getCollectionEntry( this );
+ final CollectionEntry ce = session.getPersistenceContextInternal().getCollectionEntry( this );
if ( ce != null ) {
sb.append(
MessageHelper.collectionInfoString(
// AST in ORM 5+, handling this type of condition is either extremely difficult or impossible. Forcing
// recreation isn't ideal, but not really any other option in ORM 4.
// Selecting a type used in where part of update statement
- // (must match condidion in org.hibernate.persister.collection.BasicCollectionPersister.doUpdateRows).
+ // (must match condition in org.hibernate.persister.collection.BasicCollectionPersister#doUpdateRows).
// See HHH-9474
Type whereType;
if ( persister.hasIndex() ) {
};
}
else {
- return EmptyIterator.INSTANCE;
+ return Collections.emptyIterator();
}
}
*
* @return The session
*/
- public final SessionImplementor getSession() {
+ public final SharedSessionContractImplementor getSession() {
return session;
}
Collection oldElements,
Collection currentElements,
String entityName,
- SessionImplementor session) throws HibernateException {
+ SharedSessionContractImplementor session) throws HibernateException {
// short-circuit(s)
if ( currentElements.size() == 0 ) {
// collect EntityIdentifier(s) of the *current* elements - add them into a HashSet for fast access
final java.util.Set currentIds = new HashSet();
final java.util.Set currentSaving = new IdentitySet();
+ final PersistenceContext persistenceContext = session.getPersistenceContextInternal();
for ( Object current : currentElements ) {
if ( current != null && ForeignKeys.isNotTransient( entityName, current, null, session ) ) {
- final EntityEntry ee = session.getPersistenceContext().getEntry( current );
+ final EntityEntry ee = persistenceContext.getEntry( current );
if ( ee != null && ee.getStatus() == Status.SAVING ) {
currentSaving.add( current );
}
Collection list,
Object entityInstance,
String entityName,
- SessionImplementor session) {
+ SharedSessionContractImplementor session) {
if ( entityInstance != null && ForeignKeys.isNotTransient( entityName, entityInstance, null, session ) ) {
final EntityPersister entityPersister = session.getFactory().getEntityPersister( entityName );
}
}
+ /**
+ * Removes entity entries that have an equal identifier with the incoming entity instance
+ *
+ * @param list The list containing the entity instances
+ * @param entityInstance The entity instance to match elements.
+ * @param entityName The entity name
+ * @param session The session
+ *
+ * @deprecated {@link #identityRemove(Collection, Object, String, SharedSessionContractImplementor)}
+ * should be used instead.
+ */
+ @Deprecated
+ public static void identityRemove(
+ Collection list,
+ Object entityInstance,
+ String entityName,
+ SessionImplementor session) {
+ identityRemove( list, entityInstance, entityName, (SharedSessionContractImplementor) session );
+ }
+
@Override
public Object getIdentifier(Object entry, int i) {
throw new UnsupportedOperationException();