From 687b28fc8d706d15b02b73d7532b2408f3014dcc Mon Sep 17 00:00:00 2001 From: Steve Ebersole Date: Tue, 3 Feb 2009 01:15:58 +0000 Subject: [PATCH] HHH-3357 : clear() performance git-svn-id: https://svn.jboss.org/repos/hibernate/core/trunk@15863 1b8cb986-b30d-0410-93ca-fae66ebed9b2 --- .../engine/StatefulPersistenceContext.java | 2 +- .../event/def/DefaultEvictEventListener.java | 2 +- .../proxy/AbstractLazyInitializer.java | 130 +++++++++++++----- .../org/hibernate/proxy/LazyInitializer.java | 121 ++++++++++------ 4 files changed, 175 insertions(+), 80 deletions(-) diff --git a/core/src/main/java/org/hibernate/engine/StatefulPersistenceContext.java b/core/src/main/java/org/hibernate/engine/StatefulPersistenceContext.java index b2391f8388..a94e616ab8 100644 --- a/core/src/main/java/org/hibernate/engine/StatefulPersistenceContext.java +++ b/core/src/main/java/org/hibernate/engine/StatefulPersistenceContext.java @@ -204,7 +204,7 @@ public class StatefulPersistenceContext implements PersistenceContext { Iterator itr = proxiesByKey.values().iterator(); while ( itr.hasNext() ) { final LazyInitializer li = ( ( HibernateProxy ) itr.next() ).getHibernateLazyInitializer(); - li.setSession( null ); + li.unsetSession(); } Map.Entry[] collectionEntryArray = IdentityMap.concurrentEntries( collectionEntries ); for ( int i = 0; i < collectionEntryArray.length; i++ ) { diff --git a/core/src/main/java/org/hibernate/event/def/DefaultEvictEventListener.java b/core/src/main/java/org/hibernate/event/def/DefaultEvictEventListener.java index 67728e9d46..bfc70cadbe 100644 --- a/core/src/main/java/org/hibernate/event/def/DefaultEvictEventListener.java +++ b/core/src/main/java/org/hibernate/event/def/DefaultEvictEventListener.java @@ -83,7 +83,7 @@ public class DefaultEvictEventListener implements EvictEventListener { doEvict( entity, key, e.getPersister(), event.getSession() ); } } - li.setSession( null ); + li.unsetSession(); } else { EntityEntry e = persistenceContext.removeEntry( object ); diff --git a/core/src/main/java/org/hibernate/proxy/AbstractLazyInitializer.java b/core/src/main/java/org/hibernate/proxy/AbstractLazyInitializer.java index 528342b56c..33d4f73933 100755 --- a/core/src/main/java/org/hibernate/proxy/AbstractLazyInitializer.java +++ b/core/src/main/java/org/hibernate/proxy/AbstractLazyInitializer.java @@ -32,54 +32,100 @@ import org.hibernate.engine.EntityKey; import org.hibernate.engine.SessionImplementor; /** - * Convenience base class for lazy initialization handlers. Centralizes the - * basic plumbing of doing lazy initialization freeing subclasses to - * acts as essentially adapters to their intended entity mode and/or + * Convenience base class for lazy initialization handlers. Centralizes the basic plumbing of doing lazy + * initialization freeing subclasses to acts as essentially adapters to their intended entity mode and/or * proxy generation strategy. * * @author Gavin King */ public abstract class AbstractLazyInitializer implements LazyInitializer { - - private Object target; - private boolean initialized; private String entityName; private Serializable id; - private transient SessionImplementor session; + private Object target; + private boolean initialized; private boolean unwrap; + private transient SessionImplementor session; + /** * For serialization from the non-pojo initializers (HHH-3309) */ protected AbstractLazyInitializer() { } - + + /** + * Main constructor. + * + * @param entityName The name of the entity being proxied. + * @param id The identifier of the entity being proxied. + * @param session The session owning the proxy. + */ protected AbstractLazyInitializer(String entityName, Serializable id, SessionImplementor session) { + this.entityName = entityName; this.id = id; this.session = session; - this.entityName = entityName; - } - - public final Serializable getIdentifier() { - return id; - } - - public final void setIdentifier(Serializable id) { - this.id = id; } + /** + * {@inheritDoc} + */ public final String getEntityName() { return entityName; } + /** + * {@inheritDoc} + */ + public final Serializable getIdentifier() { + return id; + } + + /** + * {@inheritDoc} + */ + public final void setIdentifier(Serializable id) { + this.id = id; + } + + /** + * {@inheritDoc} + */ public final boolean isUninitialized() { return !initialized; } + /** + * {@inheritDoc} + */ public final SessionImplementor getSession() { return session; } + /** + * {@inheritDoc} + */ + public final void setSession(SessionImplementor s) throws HibernateException { + if ( s != session ) { + if ( isConnectedToSession() ) { + //TODO: perhaps this should be some other RuntimeException... + throw new HibernateException("illegally attempted to associate a proxy with two open Sessions"); + } + else { + session = s; + } + } + } + + /** + * {@inheritDoc} + */ + public void unsetSession() { + session = null; + } + + /** + * {@inheritDoc} + */ public final void initialize() throws HibernateException { if (!initialized) { if ( session==null ) { @@ -110,28 +156,16 @@ public abstract class AbstractLazyInitializer implements LazyInitializer { } } - public final void setSession(SessionImplementor s) throws HibernateException { - if (s!=session) { - if ( isConnectedToSession() ) { - //TODO: perhaps this should be some other RuntimeException... - throw new HibernateException("illegally attempted to associate a proxy with two open Sessions"); - } - else { - session = s; - } - } - } - + /** + * Getter for property 'connectedToSession'. + * + * @return Value for property 'connectedToSession'. + */ protected final boolean isConnectedToSession() { - return session!=null && - session.isOpen() && + return session!=null && + session.isOpen() && session.getPersistenceContext().containsProxy(this); } - - public final void setImplementation(Object target) { - this.target = target; - initialized = true; - } /** * Return the underlying persistent object, initializing if necessary @@ -141,6 +175,14 @@ public abstract class AbstractLazyInitializer implements LazyInitializer { return target; } + /** + * {@inheritDoc} + */ + public final void setImplementation(Object target) { + this.target = target; + initialized = true; + } + /** * Return the underlying persistent object in the given Session, or null, * do not initialize the proxy @@ -150,20 +192,32 @@ public abstract class AbstractLazyInitializer implements LazyInitializer { getIdentifier(), s.getFactory().getEntityPersister( getEntityName() ), s.getEntityMode() - ); + ); return s.getPersistenceContext().getEntity( entityKey ); } + /** + * Getter for property 'target'. + *

+ * Same as {@link #getImplementation()} except that this method will not force initialization. + * + * @return Value for property 'target'. + */ protected final Object getTarget() { return target; } + /** + * {@inheritDoc} + */ public boolean isUnwrap() { return unwrap; } + /** + * {@inheritDoc} + */ public void setUnwrap(boolean unwrap) { this.unwrap = unwrap; } - } diff --git a/core/src/main/java/org/hibernate/proxy/LazyInitializer.java b/core/src/main/java/org/hibernate/proxy/LazyInitializer.java index abb5694a3e..621fb0404c 100644 --- a/core/src/main/java/org/hibernate/proxy/LazyInitializer.java +++ b/core/src/main/java/org/hibernate/proxy/LazyInitializer.java @@ -31,68 +31,109 @@ import org.hibernate.engine.SessionImplementor; /** * Handles fetching of the underlying entity for a proxy + * * @author Gavin King + * @author Steve Ebersole */ public interface LazyInitializer { - /** - * Initialize the proxy, fetching the target - * entity if necessary + * Initialize the proxy, fetching the target entity if necessary. + * + * @throws HibernateException Indicates a problem initializing the proxy. */ - public abstract void initialize() throws HibernateException; - - /** - * Get the identifier held by the proxy - */ - public abstract Serializable getIdentifier(); + public void initialize() throws HibernateException; /** - * Set the identifier property of the proxy + * Retrieve the identifier value for the enity our owning proxy represents. + * + * @return The identifier value. */ - public abstract void setIdentifier(Serializable id); - + public Serializable getIdentifier(); + /** - * Get the entity name + * Set the identifier value for the enity our owning proxy represents. + * + * @param id The identifier value. */ - public abstract String getEntityName(); - + public void setIdentifier(Serializable id); + /** - * Get the actual class of the entity (don't - * use this, use the entityName) + * The entity-name of the entity our owning proxy represents. + * + * @return The entity-name. */ - public abstract Class getPersistentClass(); - + public String getEntityName(); + + /** + * Get the actual class of the entity. Generally, {@link #getEntityName()} should be used instead. + * + * @return The actual entity class. + */ + public Class getPersistentClass(); + /** * Is the proxy uninitialzed? + * + * @return True if uninitialized; false otherwise. */ - public abstract boolean isUninitialized(); - - /** - * Initialize the proxy manually - */ - public abstract void setImplementation(Object target); - - /** - * Get the session, if this proxy is attached - */ - public abstract SessionImplementor getSession(); - - /** - * Attach the proxy to a session - */ - public abstract void setSession(SessionImplementor s) throws HibernateException; + public boolean isUninitialized(); /** * Return the underlying persistent object, initializing if necessary + * + * @return The underlying target entity. */ - public abstract Object getImplementation(); + public Object getImplementation(); /** - * Return the underlying persistent object in the given Session, or null + * Return the underlying persistent object in the given session, or null if not contained in this session's + * persistence context. + * + * @param session The session to check + * + * @return The target, or null. + * + * @throws HibernateException Indicates problem locating the target. */ - public abstract Object getImplementation(SessionImplementor s) - throws HibernateException; + public abstract Object getImplementation(SessionImplementor session) throws HibernateException; + + /** + * Initialize the proxy manually by injecting its target. + * + * @param target The proxy target (the actual entity being proxied). + */ + public void setImplementation(Object target); + + /** + * Get the session to which this proxy is associated, or null if it is not attached. + * + * @return The associated session. + */ + public SessionImplementor getSession(); + + /** + * Associate the proxy with the given session. + *

+ * Care should be given to make certain that the proxy is added to the session's persistence context as well + * to maintain the symetry of the association. That must be done seperately as this method simply sets an + * internal reference. We do also check that if there is already an associated session that the proxy + * reference was removed from that previous session's persistence contet. + * + * @param session The session + * @throws HibernateException Indicates that the proxy was still contained in the persistence context of the + * "previous session". + */ + public void setSession(SessionImplementor session) throws HibernateException; + + /** + * Unset this initializer's reference to session. It is assumed that the caller is also taking care or + * cleaning up the owning proxy's reference in the persistence context. + *

+ * Generally speaking this is intended to be called only during {@link org.hibernate.Session#evict} and + * {@link org.hibernate.Session#clear} processing; most other use-cases should call {@link #setSession} instead. + */ + public void unsetSession(); public void setUnwrap(boolean unwrap); public boolean isUnwrap(); -} \ No newline at end of file +}