📄 persistentcollection.java
字号:
//$Id: PersistentCollection.java,v 1.20.2.14 2003/11/27 09:30:48 oneovthafew Exp $package net.sf.hibernate.collection;import java.io.Serializable;import java.sql.PreparedStatement;import java.sql.ResultSet;import java.sql.SQLException;import java.util.ArrayList;import java.util.Collection;import java.util.Iterator;import java.util.List;import java.util.ListIterator;import net.sf.hibernate.AssertionFailure;import net.sf.hibernate.HibernateException;import net.sf.hibernate.LazyInitializationException;import net.sf.hibernate.engine.CollectionSnapshot;import net.sf.hibernate.engine.SessionImplementor;import net.sf.hibernate.type.Type;import net.sf.hibernate.util.EmptyIterator;import org.apache.commons.logging.LogFactory;/** * Persistent collections are treated as value objects by Hibernate. * ie. they have no independent existence beyond the object holding * a reference to them. Unlike instances of entity classes, they are * automatically deleted when unreferenced and automatically become * persistent when held by a persistent object. Collections can be * passed between different objects (change "roles") and this might * cause their elements to move from one database table to another.<br> * <br> * Hibernate "wraps" a java collection in an instance of * PersistentCollection. This mechanism is designed to support * tracking of changes to the collection's persistent state and * lazy instantiation of collection elements. The downside is that * only certain abstract collection types are supported and any * extra semantics are lost<br> * <br> * Applications should <em>never</em> use classes in this package * directly, unless extending the "framework" here.<br> * <br> * Changes to <em>structure</em> of the collection are recorded by the * collection calling back to the session. Changes to mutable * elements (ie. composite elements) are discovered by cloning their * state when the collection is initialized and comparing at flush * time. * * @author Gavin King */public abstract class PersistentCollection implements Serializable { private transient SessionImplementor session; private boolean initialized; private transient List additions; private CollectionSnapshot collectionSnapshot; private transient boolean directlyAccessible; //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 */ public final void read() { initialize(false); } /** * Is the collection currently connected to an open session? */ private final boolean isConnectedToSession() { return session!=null && session.isOpen(); } /** * Called by any writer method of the collection interface */ protected final void write() { initialize(true); if ( isConnectedToSession() ) { session.dirty(this); } else { collectionSnapshot.setDirty(); } } /** * Is this collection in a state that would allow us to * "queue" additions? */ private boolean isQueueAdditionEnabled() { return !initialized && isConnectedToSession() && session.isInverseCollection(this); } /** * Queue an addition */ protected final boolean queueAdd(Object element) { if ( isQueueAdditionEnabled() ) { if (additions==null) additions = new ArrayList(10); additions.add(element); session.dirty(this); //needed so that we remove this collection from the JCS cache return true; } else { return false; } } /** * Queue additions */ protected final boolean queueAddAll(Collection coll) { if ( isQueueAdditionEnabled() ) { if (additions==null) additions = new ArrayList(20); additions.addAll(coll); return true; } else { return false; } } /** * After reading all existing elements from the database, * add the queued elements to the underlying collection. */ public void delayedAddAll(Collection coll) { throw new AssertionFailure("Collection does not support delayed initialization"); } /** * After flushing, clear any "queued" additions, since the * database state is now synchronized with the memory state. */ public void postFlush() { if (additions!=null) additions=null; } /** * Not called by Hibernate, but used by non-JDK serialization, * eg. SOAP libraries. */ public PersistentCollection() {} protected PersistentCollection(SessionImplementor session) { this.session = session; } /** * Return the collection. Overridden on ArrayHolder! */ public Object getInitialValue() throws HibernateException { return this; } /** * return the user-visible collection (or array) instance */ public Object getCachedValue() { initialized = true; //TODO: only needed for query FETCH, so should move out of here return this; } /** * Called just before reading any rows from the JDBC result set */ public void beginRead() { // override on some subclasses } /** * Called after reading all rows from the JDBC result set */ public boolean endRead() { //override on some subclasses initialized = true; //do this bit after setting initialized to true or it will recurse if (additions!=null) { delayedAddAll(additions); additions=null; 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(boolean writing) { if (!initialized) { if ( isConnectedToSession() ) { try { session.initializeCollection(this, writing); } catch (Exception e) { LogFactory.getLog(PersistentCollection.class).error( "Failed to lazily initialize a collection", e ); throw new LazyInitializationException("Failed to lazily initialize a collection", e); } } else { throw new LazyInitializationException("Failed to lazily initialize a collection - no Session"); } } } protected final void setInitialized(boolean initialized) { this.initialized = initialized; } protected final void setDirectlyAccessible(boolean directlyAccessible) { this.directlyAccessible = directlyAccessible; } /** * Could the application possibly have a direct reference to * the underlying collection implementation? */ public boolean isDirectlyAccessible() { return directlyAccessible; } /** * Disassociate this collection from the given session. * @return true if this was currently associated with the given session */ public final boolean unsetSession(SessionImplementor currentSession) { if (currentSession==this.session) { this.session=null; return true; } else { return false; } } /** * 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 */ public final boolean setCurrentSession(SessionImplementor session) throws HibernateException { if (session==this.session) { return false; } else { if ( isConnectedToSession() ) { throw new HibernateException("Illegal attempt to associate a collection with two open sessions"); } else { this.session = session; return true; } } } /** * Iterate all collection entries, during update of the database */ public abstract Iterator entries(); /** * Read a row from the JDBC result set */ public abstract Object readFrom(ResultSet rs, CollectionPersister role, Object owner) throws HibernateException, SQLException; /** * Write a row to the JDBC prepared statement */ public abstract void writeTo(PreparedStatement st, CollectionPersister role, Object entry, int i, boolean writeOrder) throws HibernateException, SQLException; /** * Get the index of the given collection entry */ public abstract Object getIndex(Object entry, int i); /** * Called before any elements are read into the collection, * allowing appropriate initializations to occur. */ public abstract void beforeInitialize(CollectionPersister persister); /** * Does the current state exactly match the snapshot? */ public abstract boolean equalsSnapshot(Type elementType) throws HibernateException; /** * Return a new snapshot of the current state */ protected abstract Serializable snapshot(CollectionPersister persister) throws HibernateException; /** * Disassemble the collection, ready for the cache */ public abstract Serializable disassemble(CollectionPersister persister) throws HibernateException; /** * Do we need to completely recreate this collection when it changes? */ public boolean needsRecreate(CollectionPersister persister) { return false; } /** * Return a new snapshot of the current state of the collection, * or null if no persister is passed */ public final Serializable getSnapshot(CollectionPersister persister) throws HibernateException { return (persister==null) ? null : snapshot(persister); } /** * To be called internally by the session, forcing * immediate initialization. */ public final void forceInitialization() throws HibernateException { //TODO: check that session is open! if (!initialized) session.initializeCollection(this, false); } /** * Does an element exist at this entry in the collection? */ public abstract boolean entryExists(Object entry, int i); //note that i parameter is now unused (delete it?) /** * Do we need to insert this element? */ public abstract boolean needsInserting(Object entry, int i, Type elemType) throws HibernateException; /** * Do we need to update this element? */ public abstract boolean needsUpdating(Object entry, int i, Type elemType) throws HibernateException; /** * Get all the elements that need deleting */ public abstract Iterator getDeletes(Type elemType) throws HibernateException; /** * Is this the wrapper for the given underlying collection instance? */ public abstract boolean isWrapper(Object collection); /** * Get the current snapshot from the session */ protected final Serializable getSnapshot() { return session.getSnapshot(this); } /** * Is this instance initialized? */ public final boolean wasInitialized() { return initialized; } /** * Does this instance have any "queued" additions? */ public final boolean hasQueuedAdditions() { return additions!=null; } /** * Iterate the "queued" additions */ public final Iterator queuedAdditionIterator() { return hasQueuedAdditions() ? additions.iterator() : EmptyIterator.INSTANCE; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -