HHH-7457 - Enable loading of collections thats been detached from session
(cherry picked from commit 467258cffa
)
This commit is contained in:
parent
98caa8e44b
commit
b810f1049f
|
@ -23,20 +23,30 @@
|
|||
*/
|
||||
package org.hibernate.collection.internal;
|
||||
|
||||
import javax.naming.NamingException;
|
||||
import java.io.Serializable;
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
|
||||
import org.hibernate.AssertionFailure;
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.LazyInitializationException;
|
||||
import org.hibernate.cfg.AvailableSettings;
|
||||
import org.hibernate.cfg.Configuration;
|
||||
import org.hibernate.collection.spi.PersistentCollection;
|
||||
import org.hibernate.engine.internal.ForeignKeys;
|
||||
import org.hibernate.engine.spi.*;
|
||||
import org.hibernate.engine.spi.CollectionEntry;
|
||||
import org.hibernate.engine.spi.EntityEntry;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.engine.spi.SessionImplementor;
|
||||
import org.hibernate.engine.spi.Status;
|
||||
import org.hibernate.engine.spi.TypedValue;
|
||||
import org.hibernate.internal.SessionFactoryRegistry;
|
||||
import org.hibernate.internal.util.MarkerObject;
|
||||
import org.hibernate.internal.util.collections.CollectionHelper;
|
||||
import org.hibernate.internal.util.collections.EmptyIterator;
|
||||
import org.hibernate.internal.util.collections.IdentitySet;
|
||||
import org.hibernate.persister.collection.CollectionPersister;
|
||||
|
@ -44,8 +54,6 @@ import org.hibernate.persister.entity.EntityPersister;
|
|||
import org.hibernate.pretty.MessageHelper;
|
||||
import org.hibernate.type.Type;
|
||||
|
||||
import javax.naming.NamingException;
|
||||
|
||||
/**
|
||||
* Base class implementing {@link org.hibernate.collection.spi.PersistentCollection}
|
||||
*
|
||||
|
@ -100,10 +108,12 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
|
|||
}
|
||||
|
||||
//Careful: these methods do not initialize the collection.
|
||||
|
||||
/**
|
||||
* Is the initialized collection empty?
|
||||
*/
|
||||
public abstract boolean empty();
|
||||
|
||||
/**
|
||||
* Called by any read-only method of the collection interface
|
||||
*/
|
||||
|
@ -125,8 +135,9 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
|
|||
if ( specjLazyLoad ) {
|
||||
specialSpecjInitialization( false );
|
||||
}
|
||||
else
|
||||
else {
|
||||
throwLazyInitializationExceptionIfNotConnected();
|
||||
}
|
||||
CollectionEntry entry = session.getPersistenceContext().getCollectionEntry( this );
|
||||
CollectionPersister persister = entry.getLoadedPersister();
|
||||
if ( persister.isExtraLazy() ) {
|
||||
|
@ -138,11 +149,12 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
|
|||
}
|
||||
}
|
||||
finally {
|
||||
if(specjLazyLoad)
|
||||
if ( specjLazyLoad ) {
|
||||
session = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
read();
|
||||
return false;
|
||||
}
|
||||
|
@ -153,8 +165,9 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
|
|||
if ( specjLazyLoad ) {
|
||||
specialSpecjInitialization( false );
|
||||
}
|
||||
else
|
||||
else {
|
||||
throwLazyInitializationExceptionIfNotConnected();
|
||||
}
|
||||
CollectionEntry entry = session.getPersistenceContext().getCollectionEntry( this );
|
||||
CollectionPersister persister = entry.getLoadedPersister();
|
||||
if ( persister.isExtraLazy() ) {
|
||||
|
@ -165,10 +178,11 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
|
|||
}
|
||||
}
|
||||
finally {
|
||||
if(specjLazyLoad)
|
||||
if ( specjLazyLoad ) {
|
||||
session = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
read();
|
||||
return null;
|
||||
}
|
||||
|
@ -179,8 +193,9 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
|
|||
if ( specjLazyLoad ) {
|
||||
specialSpecjInitialization( false );
|
||||
}
|
||||
else
|
||||
else {
|
||||
throwLazyInitializationExceptionIfNotConnected();
|
||||
}
|
||||
CollectionEntry entry = session.getPersistenceContext().getCollectionEntry( this );
|
||||
CollectionPersister persister = entry.getLoadedPersister();
|
||||
if ( persister.isExtraLazy() ) {
|
||||
|
@ -191,10 +206,11 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
|
|||
}
|
||||
}
|
||||
finally {
|
||||
if(specjLazyLoad)
|
||||
if ( specjLazyLoad ) {
|
||||
session = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
read();
|
||||
return null;
|
||||
}
|
||||
|
@ -246,6 +262,7 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
|
|||
isConnectedToSession() &&
|
||||
isInverseCollection();
|
||||
}
|
||||
|
||||
/**
|
||||
* Is this collection in a state that would allow us to
|
||||
* "queue" puts? This is a special case, because of orphan
|
||||
|
@ -257,6 +274,7 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
|
|||
isConnectedToSession() &&
|
||||
isInverseOneToManyOrNoOrphanDelete();
|
||||
}
|
||||
|
||||
/**
|
||||
* Is this collection in a state that would allow us to
|
||||
* "queue" clear? This is a special case, because of orphan
|
||||
|
@ -348,7 +366,8 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
|
|||
* Not called by Hibernate, but used by non-JDK serialization,
|
||||
* eg. SOAP libraries.
|
||||
*/
|
||||
public AbstractPersistentCollection() {}
|
||||
public AbstractPersistentCollection() {
|
||||
}
|
||||
|
||||
protected AbstractPersistentCollection(SessionImplementor session) {
|
||||
this.session = session;
|
||||
|
@ -394,7 +413,9 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
|
|||
/**
|
||||
* Initialize the collection, if possible, wrapping any exceptions
|
||||
* in a runtime exception
|
||||
*
|
||||
* @param writing currently obsolete
|
||||
*
|
||||
* @throws LazyInitializationException if we cannot initialize
|
||||
*/
|
||||
protected final void initialize(boolean writing) {
|
||||
|
@ -491,6 +512,7 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
|
|||
|
||||
/**
|
||||
* Disassociate this collection from the given session.
|
||||
*
|
||||
* @return true if this was currently associated with the given session
|
||||
*/
|
||||
public final boolean unsetSession(SessionImplementor currentSession) {
|
||||
|
@ -506,7 +528,11 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
|
|||
|
||||
protected void prepareForPossibleSpecialSpecjInitialization() {
|
||||
if ( session != null ) {
|
||||
specjLazyLoad = Boolean.parseBoolean( session.getFactory().getProperties().getProperty( AvailableSettings.ENABLE_LAZY_LOAD_NO_TRANS));
|
||||
specjLazyLoad = Boolean.parseBoolean(
|
||||
session.getFactory()
|
||||
.getProperties()
|
||||
.getProperty( AvailableSettings.ENABLE_LAZY_LOAD_NO_TRANS )
|
||||
);
|
||||
|
||||
if ( specjLazyLoad && sessionFactoryUuid == null ) {
|
||||
try {
|
||||
|
@ -522,7 +548,9 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
|
|||
|
||||
/**
|
||||
* Associate the collection with the given session.
|
||||
*
|
||||
* @return false if the collection was already associated with the session
|
||||
*
|
||||
* @throws HibernateException if the collection was already associated
|
||||
* with another open session
|
||||
*/
|
||||
|
@ -608,6 +636,7 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
|
|||
public final boolean hasQueuedOperations() {
|
||||
return operationQueue != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterate the "queued" additions
|
||||
*/
|
||||
|
@ -615,12 +644,15 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
|
|||
if ( hasQueuedOperations() ) {
|
||||
return new Iterator() {
|
||||
int i = 0;
|
||||
|
||||
public Object next() {
|
||||
return operationQueue.get( i++ ).getAddedInstance();
|
||||
}
|
||||
|
||||
public boolean hasNext() {
|
||||
return i < operationQueue.size();
|
||||
}
|
||||
|
||||
public void remove() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
@ -630,6 +662,7 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
|
|||
return EmptyIterator.INSTANCE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterate the "queued" additions
|
||||
*/
|
||||
|
@ -653,11 +686,15 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
|
|||
* Called before inserting rows, to ensure that any surrogate keys
|
||||
* are fully generated
|
||||
*/
|
||||
public void preInsert(CollectionPersister persister) throws HibernateException {}
|
||||
public void preInsert(CollectionPersister persister) throws HibernateException {
|
||||
}
|
||||
|
||||
/**
|
||||
* Called after inserting a row, to fetch the natively generated id
|
||||
*/
|
||||
public void afterRowInsert(CollectionPersister persister, Object entry, int i) throws HibernateException {}
|
||||
public void afterRowInsert(CollectionPersister persister, Object entry, int i) throws HibernateException {
|
||||
}
|
||||
|
||||
/**
|
||||
* get all "orphaned" elements
|
||||
*/
|
||||
|
@ -677,6 +714,7 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
|
|||
public IteratorProxy(Iterator itr) {
|
||||
this.itr = itr;
|
||||
}
|
||||
|
||||
public boolean hasNext() {
|
||||
return itr.hasNext();
|
||||
}
|
||||
|
@ -957,7 +995,9 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
|
|||
*/
|
||||
protected interface DelayedOperation {
|
||||
public void operate();
|
||||
|
||||
public Object getAddedInstance();
|
||||
|
||||
public Object getOrphan();
|
||||
}
|
||||
|
||||
|
|
|
@ -56,6 +56,7 @@ public abstract class AbstractLazyInitializer implements LazyInitializer {
|
|||
|
||||
private String sessionFactoryUuid;
|
||||
private boolean specjLazyLoad = false;
|
||||
|
||||
/**
|
||||
* For serialization from the non-pojo initializers (HHH-3309)
|
||||
*/
|
||||
|
@ -211,7 +212,11 @@ public abstract class AbstractLazyInitializer implements LazyInitializer {
|
|||
protected void prepareForPossibleSpecialSpecjInitialization() {
|
||||
if ( session != null ) {
|
||||
specjLazyLoad =
|
||||
Boolean.parseBoolean( session.getFactory().getProperties().getProperty( AvailableSettings.ENABLE_LAZY_LOAD_NO_TRANS));
|
||||
Boolean.parseBoolean(
|
||||
session.getFactory()
|
||||
.getProperties()
|
||||
.getProperty( AvailableSettings.ENABLE_LAZY_LOAD_NO_TRANS )
|
||||
);
|
||||
|
||||
if ( specjLazyLoad && sessionFactoryUuid == null ) {
|
||||
try {
|
||||
|
@ -286,11 +291,13 @@ public abstract class AbstractLazyInitializer implements LazyInitializer {
|
|||
private void errorIfReadOnlySettingNotAvailable() {
|
||||
if ( session == null ) {
|
||||
throw new TransientObjectException(
|
||||
"Proxy is detached (i.e, session is null). The read-only/modifiable setting is only accessible when the proxy is associated with an open session." );
|
||||
"Proxy is detached (i.e, session is null). The read-only/modifiable setting is only accessible when the proxy is associated with an open session."
|
||||
);
|
||||
}
|
||||
if ( session.isClosed() ) {
|
||||
throw new SessionException(
|
||||
"Session is closed. The read-only/modifiable setting is only accessible when the proxy is associated with an open session." );
|
||||
"Session is closed. The read-only/modifiable setting is only accessible when the proxy is associated with an open session."
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -322,13 +329,14 @@ public abstract class AbstractLazyInitializer implements LazyInitializer {
|
|||
/**
|
||||
* Get the read-only/modifiable setting that should be put in affect when it is
|
||||
* attached to a session.
|
||||
*
|
||||
* <p/>
|
||||
* This method should only be called during serialization when read-only/modifiable setting
|
||||
* is not available (i.e., isReadOnlySettingAvailable() == false)
|
||||
*
|
||||
* @return null, if the default setting should be used;
|
||||
* true, for read-only;
|
||||
* false, for modifiable
|
||||
*
|
||||
* @throws IllegalStateException if isReadOnlySettingAvailable() == true
|
||||
*/
|
||||
protected final Boolean isReadOnlyBeforeAttachedToSession() {
|
||||
|
@ -343,12 +351,13 @@ public abstract class AbstractLazyInitializer implements LazyInitializer {
|
|||
/**
|
||||
* Set the read-only/modifiable setting that should be put in affect when it is
|
||||
* attached to a session.
|
||||
*
|
||||
* <p/>
|
||||
* This method should only be called during deserialization, before associating
|
||||
* the proxy with a session.
|
||||
*
|
||||
* @param readOnlyBeforeAttachedToSession, the read-only/modifiable setting to use when
|
||||
* associated with a session; null indicates that the default should be used.
|
||||
*
|
||||
* @throws IllegalStateException if isReadOnlySettingAvailable() == true
|
||||
*/
|
||||
/* package-private */
|
||||
|
|
Loading…
Reference in New Issue