Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or .
*/
package org.hibernate.collection.internal;
import java.io.Serializable;
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 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.collection.spi.PersistentCollection;
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.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;
import org.hibernate.type.PostgresUUIDType;
import org.hibernate.type.StringType;
import org.hibernate.type.Type;
import org.hibernate.type.UUIDBinaryType;
import org.hibernate.type.UUIDCharType;
/**
* Base class implementing {@link org.hibernate.collection.spi.PersistentCollection}
*
* @author Gavin King
*/
public abstract class AbstractPersistentCollection implements Serializable, PersistentCollection {
private static final CoreMessageLogger LOG = CoreLogging.messageLogger( AbstractPersistentCollection.class );
private transient SharedSessionContractImplementor session;
private boolean isTempSession = false;
private boolean initialized;
private transient List operationQueue;
private transient boolean directlyAccessible;
private transient boolean initializing;
private Object owner;
private int cachedSize = -1;
private String role;
private Serializable key;
// 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;
private boolean allowLoadOutsideTransaction;
/**
* Not called by Hibernate, but used by non-JDK serialization,
* eg. SOAP libraries.
*/
public AbstractPersistentCollection() {
}
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;
}
@Override
public final Serializable getKey() {
return key;
}
@Override
public final boolean isUnreferenced() {
return role == null;
}
@Override
public final boolean isDirty() {
return dirty;
}
@Override
public boolean isElementRemoved() {
return elementRemoved;
}
@Override
public final void clearDirty() {
dirty = false;
elementRemoved = false;
}
@Override
public final void dirty() {
dirty = true;
}
@Override
public final Serializable getStoredSnapshot() {
return storedSnapshot;
}
//Careful: these methods do not initialize the collection.
@Override
public abstract boolean empty();
/**
* Called by any read-only method of the collection interface
*/
protected final void read() {
initialize( false );
}
/**
* Called by the {@link Collection#size} method
*/
@SuppressWarnings({"JavaDoc"})
protected boolean readSize() {
if ( !initialized ) {
if ( cachedSize != -1 && !hasQueuedOperations() ) {
return true;
}
else {
final boolean isExtraLazy = withTemporarySessionIfNeeded(
new LazyInitializationWork() {
@Override
public Boolean doWork() {
final CollectionEntry entry = session.getPersistenceContextInternal().getCollectionEntry( AbstractPersistentCollection.this );
if ( entry != null ) {
final CollectionPersister persister = entry.getLoadedPersister();
if ( persister.isExtraLazy() ) {
if ( hasQueuedOperations() ) {
session.flush();
}
cachedSize = persister.getSize( entry.getLoadedKey(), session );
return true;
}
else {
read();
}
}
else{
throwLazyInitializationExceptionIfNotConnected();
}
return false;
}
}
);
if ( isExtraLazy ) {
return true;
}
}
}
return false;
}
/**
* TBH not sure why this is public
*
* @param The java type of the return for this LazyInitializationWork
*/
public static interface LazyInitializationWork {
/**
* Do the represented work and return the result.
*
* @return The result
*/
public T doWork();
}
private T withTemporarySessionIfNeeded(LazyInitializationWork lazyInitializationWork) {
SharedSessionContractImplementor tempSession = null;
if ( session == null ) {
if ( allowLoadOutsideTransaction ) {
tempSession = openTemporarySessionForLoading();
}
else {
throwLazyInitializationException( "could not initialize proxy - no Session" );
}
}
else if ( !session.isOpenOrWaitingForAutoClose() ) {
if ( allowLoadOutsideTransaction ) {
tempSession = openTemporarySessionForLoading();
}
else {
throwLazyInitializationException( "could not initialize proxy - the owning Session was closed" );
}
}
else if ( !session.isConnected() ) {
if ( allowLoadOutsideTransaction ) {
tempSession = openTemporarySessionForLoading();
}
else {
throwLazyInitializationException( "could not initialize proxy - the owning Session is disconnected" );
}
}
SharedSessionContractImplementor originalSession = null;
boolean isJTA = false;
if ( tempSession != null ) {
isTempSession = true;
originalSession = session;
session = tempSession;
isJTA = session.getTransactionCoordinator().getTransactionCoordinatorBuilder().isJta();
if ( !isJTA ) {
// Explicitly handle the transactions only if we're not in
// a JTA environment. A lazy loading temporary session can
// be created even if a current session and transaction are
// open (ex: session.clear() was used). We must prevent
// multiple transactions.
session.beginTransaction();
}
session.getPersistenceContextInternal().addUninitializedDetachedCollection(
session.getFactory().getCollectionPersister( getRole() ),
this
);
}
try {
return lazyInitializationWork.doWork();
}
finally {
if ( tempSession != null ) {
// make sure the just opened temp session gets closed!
isTempSession = false;
session = originalSession;
try {
if ( !isJTA ) {
tempSession.getTransaction().commit();
}
tempSession.close();
}
catch (Exception e) {
LOG.warn( "Unable to close temporary session used to load lazy collection associated to no session" );
}
}
else {
if ( !session.isTransactionInProgress() ) {
session.getJdbcCoordinator().afterTransaction();
}
}
}
}
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 );
final SharedSessionContractImplementor session = (SharedSessionContractImplementor) sf.openSession();
session.getPersistenceContextInternal().setDefaultReadOnly( true );
session.setFlushMode( FlushMode.MANUAL );
return session;
}
protected Boolean readIndexExistence(final Object index) {
if ( !initialized ) {
final Boolean extraLazyExistenceCheck = withTemporarySessionIfNeeded(
new LazyInitializationWork() {
@Override
public Boolean doWork() {
final CollectionEntry entry = session.getPersistenceContextInternal().getCollectionEntry( AbstractPersistentCollection.this );
final CollectionPersister persister = entry.getLoadedPersister();
if ( persister.isExtraLazy() ) {
if ( hasQueuedOperations() ) {
session.flush();
}
return persister.indexExists( entry.getLoadedKey(), index, session );
}
else {
read();
}
return null;
}
}
);
if ( extraLazyExistenceCheck != null ) {
return extraLazyExistenceCheck;
}
}
return null;
}
protected Boolean readElementExistence(final Object element) {
if ( !initialized ) {
final Boolean extraLazyExistenceCheck = withTemporarySessionIfNeeded(
new LazyInitializationWork() {
@Override
public Boolean doWork() {
final CollectionEntry entry = session.getPersistenceContextInternal().getCollectionEntry( AbstractPersistentCollection.this );
final CollectionPersister persister = entry.getLoadedPersister();
if ( persister.isExtraLazy() ) {
if ( hasQueuedOperations() ) {
session.flush();
}
return persister.elementExists( entry.getLoadedKey(), element, session );
}
else {
read();
}
return null;
}
}
);
if ( extraLazyExistenceCheck != null ) {
return extraLazyExistenceCheck;
}
}
return null;
}
protected static final Object UNKNOWN = new MarkerObject( "UNKNOWN" );
protected Object readElementByIndex(final Object index) {
if ( !initialized ) {
class ExtraLazyElementByIndexReader implements LazyInitializationWork {
private boolean isExtraLazy;
private Object element;
@Override
public Object doWork() {
final CollectionEntry entry = session.getPersistenceContextInternal().getCollectionEntry( AbstractPersistentCollection.this );
final CollectionPersister persister = entry.getLoadedPersister();
isExtraLazy = persister.isExtraLazy();
if ( isExtraLazy ) {
if ( hasQueuedOperations() ) {
session.flush();
}
element = persister.getElementByIndex( entry.getLoadedKey(), index, session, owner );
}
else {
read();
}
return null;
}
}
final ExtraLazyElementByIndexReader reader = new ExtraLazyElementByIndexReader();
//noinspection unchecked
withTemporarySessionIfNeeded( reader );
if ( reader.isExtraLazy ) {
return reader.element;
}
}
return UNKNOWN;
}
protected int getCachedSize() {
return cachedSize;
}
protected boolean isConnectedToSession() {
return session != null
&& session.isOpen()
&& session.getPersistenceContextInternal().containsCollection( this );
}
protected boolean isInitialized() {
return initialized;
}
/**
* Called by any writer method of the collection interface
*/
protected final void write() {
initialize( true );
dirty();
}
/**
* Is this collection in a state that would allow us to
* "queue" operations?
*/
@SuppressWarnings({"JavaDoc"})
protected boolean isOperationQueueEnabled() {
return !initialized
&& isConnectedToSession()
&& isInverseCollection();
}
/**
* Is this collection in a state that would allow us to
* "queue" puts? This is a special case, because of orphan
* delete.
*/
@SuppressWarnings({"JavaDoc"})
protected boolean isPutQueueEnabled() {
return !initialized
&& isConnectedToSession()
&& isInverseOneToManyOrNoOrphanDelete();
}
/**
* Is this collection in a state that would allow us to
* "queue" clear? This is a special case, because of orphan
* delete.
*/
@SuppressWarnings({"JavaDoc"})
protected boolean isClearQueueEnabled() {
return !initialized
&& isConnectedToSession()
&& isInverseCollectionNoOrphanDelete();
}
/**
* Is this the "inverse" end of a bidirectional association?
*/
@SuppressWarnings({"JavaDoc"})
protected boolean isInverseCollection() {
final CollectionEntry ce = session.getPersistenceContextInternal().getCollectionEntry( this );
return ce != null && ce.getLoadedPersister().isInverse();
}
/**
* Is this the "inverse" end of a bidirectional association with
* no orphan delete enabled?
*/
@SuppressWarnings({"JavaDoc"})
protected boolean isInverseCollectionNoOrphanDelete() {
final CollectionEntry ce = session.getPersistenceContextInternal().getCollectionEntry( this );
if ( ce == null ) {
return false;
}
final CollectionPersister loadedPersister = ce.getLoadedPersister();
return loadedPersister.isInverse() && !loadedPersister.hasOrphanDelete();
}
/**
* Is this the "inverse" end of a bidirectional one-to-many, or
* of a collection with no orphan delete?
*/
@SuppressWarnings({"JavaDoc"})
protected boolean isInverseOneToManyOrNoOrphanDelete() {
final CollectionEntry ce = session.getPersistenceContextInternal().getCollectionEntry( this );
if ( ce == null ) {
return false;
}
final CollectionPersister loadedPersister = ce.getLoadedPersister();
return loadedPersister.isInverse() && ( loadedPersister.isOneToMany() || !loadedPersister.hasOrphanDelete() );
}
/**
* Queue an addition
*/
@SuppressWarnings({"JavaDoc"})
protected final void queueOperation(DelayedOperation operation) {
if ( operationQueue == null ) {
operationQueue = new ArrayList( 10 );
}
operationQueue.add( operation );
//needed so that we remove this collection from the second-level cache
dirty = true;
}
/**
* Replace entity instances with copy in {@code copyCache}/.
*
* @param copyCache - mapping from entity in the process of being
* merged to managed copy.
*/
public final void replaceQueuedOperationValues(CollectionPersister persister, Map copyCache) {
for ( DelayedOperation operation : operationQueue ) {
if ( ValueDelayedOperation.class.isInstance( operation ) ) {
( (ValueDelayedOperation) operation ).replace( persister, copyCache );
}
}
}
/**
* After reading all existing elements from the database,
* add the queued elements to the underlying collection.
*/
protected final void performQueuedOperations() {
for ( DelayedOperation operation : operationQueue ) {
operation.operate();
}
clearOperationQueue();
}
@Override
public void setSnapshot(Serializable key, String role, Serializable snapshot) {
this.key = key;
this.role = role;
this.storedSnapshot = snapshot;
}
@Override
public void postAction() {
clearOperationQueue();
cachedSize = -1;
clearDirty();
}
public final void clearOperationQueue() {
operationQueue = null;
}
@Override
public Object getValue() {
return this;
}
@Override
public void beginRead() {
// override on some subclasses
initializing = true;
}
@Override
public boolean endRead() {
//override on some subclasses
return afterInitialize();
}
@Override
public boolean afterInitialize() {
setInitialized();
//do this bit after setting initialized to true or it will recurse
if ( hasQueuedOperations() ) {
performQueuedOperations();
cachedSize = -1;
return false;
}
else {
return true;
}
}
/**
* 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(final boolean writing) {
if ( initialized ) {
return;
}
withTemporarySessionIfNeeded(
new LazyInitializationWork