SessionImpl.java in  » Database-ORM » hibernate » org » hibernate » impl » Java Source Code / Java Documentation Java Source Code and Java Documentation

Home
Java Source Code / Java Documentation
1.6.0 JDK Core
2.6.0 JDK Modules
3.6.0 JDK Modules com.sun
4.6.0 JDK Modules com.sun.java
5.6.0 JDK Modules sun
6.6.0 JDK Platform
7.Ajax
8.Apache Harmony Java SE
9.Aspect oriented
10.Authentication Authorization
11.Blogger System
12.Build
13.Byte Code
14.Cache
15.Chart
16.Chat
17.Code Analyzer
18.Collaboration
19.Content Management System
20.Database Client
21.Database DBMS
22.Database JDBC Connection Pool
23.Database ORM
24.Development
25.EJB Server
26.ERP CRM Financial
27.ESB
28.Forum
29.Game
30.GIS
31.Graphic 3D
32.Graphic Library
33.Groupware
34.HTML Parser
35.IDE
36.IDE Eclipse
37.IDE Netbeans
38.Installer
39.Internationalization Localization
40.Inversion of Control
41.Issue Tracking
42.J2EE
43.J2ME
44.JBoss
45.JMS
46.JMX
47.Library
48.Mail Clients
49.Music
50.Natural Language Processing
51.Net
52.Parser
53.PDF
54.Portal
55.Profiler
56.Project Management
57.Report
58.RSS RDF
59.Rule Engine
60.Science
61.Scripting
62.Search Engine
63.Security
64.Sevlet Container
65.Source Control
66.Swing Library
67.Template Engine
68.Test Coverage
69.Testing
70.UML
71.Web Crawler
72.Web Framework
73.Web Mail
74.Web Server
75.Web Services
76.Web Services apache cxf 2.2.6
77.Web Services AXIS2
78.Wiki Engine
79.Workflow Engines
80.XML
81.XML UI
Java Source Code / Java Documentation  » Database ORM » hibernate » org.hibernate.impl 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


        /*
         * Hibernate, Relational Persistence for Idiomatic Java
         *
         * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
         * indicated by the @author tags or express copyright attribution
         * statements applied by the authors.  All third-party contributions are
         * distributed under license by Red Hat Middleware LLC.
         *
         * This copyrighted material is made available to anyone wishing to use, modify,
         * copy, or redistribute it subject to the terms and conditions of the GNU
         * Lesser General Public License, as published by the Free Software Foundation.
         *
         * This program is distributed in the hope that it will be useful,
         * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
         * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
         * for more details.
         *
         * You should have received a copy of the GNU Lesser General Public License
         * along with this distribution; if not, write to:
         * Free Software Foundation, Inc.
         * 51 Franklin Street, Fifth Floor
         * Boston, MA  02110-1301  USA
         *
         */
        package org.hibernate.impl;

        import java.io.IOException;
        import java.io.ObjectInputStream;
        import java.io.ObjectOutputStream;
        import java.io.Serializable;
        import java.io.ByteArrayOutputStream;
        import java.io.ByteArrayInputStream;
        import java.sql.Connection;
        import java.sql.SQLException;
        import java.util.Collection;
        import java.util.Collections;
        import java.util.HashMap;
        import java.util.HashSet;
        import java.util.Iterator;
        import java.util.List;
        import java.util.Map;
        import java.util.Set;

        import org.slf4j.Logger;
        import org.slf4j.LoggerFactory;

        import org.hibernate.CacheMode;
        import org.hibernate.ConnectionReleaseMode;
        import org.hibernate.Criteria;
        import org.hibernate.EntityMode;
        import org.hibernate.Filter;
        import org.hibernate.FlushMode;
        import org.hibernate.HibernateException;
        import org.hibernate.Interceptor;
        import org.hibernate.LockMode;
        import org.hibernate.MappingException;
        import org.hibernate.ObjectDeletedException;
        import org.hibernate.Query;
        import org.hibernate.QueryException;
        import org.hibernate.ReplicationMode;
        import org.hibernate.SQLQuery;
        import org.hibernate.ScrollMode;
        import org.hibernate.ScrollableResults;
        import org.hibernate.Session;
        import org.hibernate.SessionException;
        import org.hibernate.SessionFactory;
        import org.hibernate.Transaction;
        import org.hibernate.TransientObjectException;
        import org.hibernate.UnresolvableObjectException;
        import org.hibernate.UnknownProfileException;
        import org.hibernate.EntityNameResolver;
        import org.hibernate.LockOptions;
        import org.hibernate.collection.PersistentCollection;
        import org.hibernate.engine.ActionQueue;
        import org.hibernate.engine.CollectionEntry;
        import org.hibernate.engine.EntityEntry;
        import org.hibernate.engine.EntityKey;
        import org.hibernate.engine.NonFlushedChanges;
        import org.hibernate.engine.PersistenceContext;
        import org.hibernate.engine.QueryParameters;
        import org.hibernate.engine.StatefulPersistenceContext;
        import org.hibernate.engine.Status;
        import org.hibernate.engine.LoadQueryInfluencers;
        import org.hibernate.engine.jdbc.LobCreationContext;
        import org.hibernate.engine.query.FilterQueryPlan;
        import org.hibernate.engine.query.HQLQueryPlan;
        import org.hibernate.engine.query.NativeSQLQueryPlan;
        import org.hibernate.engine.query.sql.NativeSQLQuerySpecification;
        import org.hibernate.event.AutoFlushEvent;
        import org.hibernate.event.AutoFlushEventListener;
        import org.hibernate.event.DeleteEvent;
        import org.hibernate.event.DeleteEventListener;
        import org.hibernate.event.DirtyCheckEvent;
        import org.hibernate.event.DirtyCheckEventListener;
        import org.hibernate.event.EventListeners;
        import org.hibernate.event.EventSource;
        import org.hibernate.event.EvictEvent;
        import org.hibernate.event.EvictEventListener;
        import org.hibernate.event.FlushEvent;
        import org.hibernate.event.FlushEventListener;
        import org.hibernate.event.InitializeCollectionEvent;
        import org.hibernate.event.InitializeCollectionEventListener;
        import org.hibernate.event.LoadEvent;
        import org.hibernate.event.LoadEventListener;
        import org.hibernate.event.LoadEventListener.LoadType;
        import org.hibernate.event.LockEvent;
        import org.hibernate.event.LockEventListener;
        import org.hibernate.event.MergeEvent;
        import org.hibernate.event.MergeEventListener;
        import org.hibernate.event.PersistEvent;
        import org.hibernate.event.PersistEventListener;
        import org.hibernate.event.RefreshEvent;
        import org.hibernate.event.RefreshEventListener;
        import org.hibernate.event.ReplicateEvent;
        import org.hibernate.event.ReplicateEventListener;
        import org.hibernate.event.SaveOrUpdateEvent;
        import org.hibernate.event.SaveOrUpdateEventListener;
        import org.hibernate.exception.JDBCExceptionHelper;
        import org.hibernate.jdbc.Batcher;
        import org.hibernate.jdbc.JDBCContext;
        import org.hibernate.jdbc.Work;
        import org.hibernate.loader.criteria.CriteriaLoader;
        import org.hibernate.loader.custom.CustomLoader;
        import org.hibernate.loader.custom.CustomQuery;
        import org.hibernate.persister.collection.CollectionPersister;
        import org.hibernate.persister.entity.EntityPersister;
        import org.hibernate.persister.entity.OuterJoinLoadable;
        import org.hibernate.pretty.MessageHelper;
        import org.hibernate.proxy.HibernateProxy;
        import org.hibernate.proxy.LazyInitializer;
        import org.hibernate.stat.SessionStatistics;
        import org.hibernate.stat.SessionStatisticsImpl;
        import org.hibernate.type.Type;
        import org.hibernate.type.SerializationException;
        import org.hibernate.util.ArrayHelper;
        import org.hibernate.util.CollectionHelper;
        import org.hibernate.util.StringHelper;

        /**
         * Concrete implementation of a Session, and also the central, organizing component
         * of Hibernate's internal implementation. As such, this class exposes two interfaces;
         * Session itself, to the application, and SessionImplementor, to other components
         * of Hibernate. This class is not threadsafe.
         *
         * @author Gavin King
         */
        public final class SessionImpl extends AbstractSessionImpl implements 
                EventSource, org.hibernate.classic.Session,
                JDBCContext.Context, LobCreationContext {

            // todo : need to find a clean way to handle the "event source" role
            // a seperate classs responsible for generating/dispatching events just duplicates most of the Session methods...
            // passing around seperate reto interceptor, factory, actionQueue, and persistentContext is not manageable...

            private static final Logger log = LoggerFactory
                    .getLogger(SessionImpl.class);

            private transient EntityMode entityMode = EntityMode.POJO;
            private transient boolean autoClear; //for EJB3

            private transient long timestamp;
            private transient FlushMode flushMode = FlushMode.AUTO;
            private transient CacheMode cacheMode = CacheMode.NORMAL;

            private transient Interceptor interceptor;

            private transient int dontFlushFromFind = 0;

            private transient ActionQueue actionQueue;
            private transient StatefulPersistenceContext persistenceContext;
            private transient JDBCContext jdbcContext;
            private transient EventListeners listeners;

            private transient boolean flushBeforeCompletionEnabled;
            private transient boolean autoCloseSessionEnabled;
            private transient ConnectionReleaseMode connectionReleaseMode;

            private transient LoadQueryInfluencers loadQueryInfluencers;

            private transient Session rootSession;
            private transient Map childSessionsByEntityMode;

            private transient EntityNameResolver entityNameResolver = new CoordinatingEntityNameResolver();

            /**
             * Constructor used in building "child sessions".
             *
             * @param parent The parent session
             * @param entityMode
             */
            private SessionImpl(SessionImpl parent, EntityMode entityMode) {
                super (parent.factory);
                this .rootSession = parent;
                this .timestamp = parent.timestamp;
                this .jdbcContext = parent.jdbcContext;
                this .interceptor = parent.interceptor;
                this .listeners = parent.listeners;
                this .actionQueue = new ActionQueue(this );
                this .entityMode = entityMode;
                this .persistenceContext = new StatefulPersistenceContext(this );
                this .flushBeforeCompletionEnabled = false;
                this .autoCloseSessionEnabled = false;
                this .connectionReleaseMode = null;

                loadQueryInfluencers = new LoadQueryInfluencers(factory);

                if (factory.getStatistics().isStatisticsEnabled()) {
                    factory.getStatisticsImplementor().openSession();
                }

                log.debug("opened session [" + entityMode + "]");
            }

            /**
             * Constructor used for openSession(...) processing, as well as construction
             * of sessions for getCurrentSession().
             *
             * @param connection The user-supplied connection to use for this session.
             * @param factory The factory from which this session was obtained
             * @param autoclose NOT USED
             * @param timestamp The timestamp for this session
             * @param interceptor The interceptor to be applied to this session
             * @param entityMode The entity-mode for this session
             * @param flushBeforeCompletionEnabled Should we auto flush before completion of transaction
             * @param autoCloseSessionEnabled Should we auto close after completion of transaction
             * @param connectionReleaseMode The mode by which we should release JDBC connections.
             */
            SessionImpl(final Connection connection,
                    final SessionFactoryImpl factory, final boolean autoclose,
                    final long timestamp, final Interceptor interceptor,
                    final EntityMode entityMode,
                    final boolean flushBeforeCompletionEnabled,
                    final boolean autoCloseSessionEnabled,
                    final ConnectionReleaseMode connectionReleaseMode) {
                super (factory);
                this .rootSession = null;
                this .timestamp = timestamp;
                this .entityMode = entityMode;
                this .interceptor = interceptor;
                this .listeners = factory.getEventListeners();
                this .actionQueue = new ActionQueue(this );
                this .persistenceContext = new StatefulPersistenceContext(this );
                this .flushBeforeCompletionEnabled = flushBeforeCompletionEnabled;
                this .autoCloseSessionEnabled = autoCloseSessionEnabled;
                this .connectionReleaseMode = connectionReleaseMode;
                this .jdbcContext = new JDBCContext(this , connection,
                        interceptor);

                loadQueryInfluencers = new LoadQueryInfluencers(factory);

                if (factory.getStatistics().isStatisticsEnabled()) {
                    factory.getStatisticsImplementor().openSession();
                }

                if (log.isDebugEnabled()) {
                    log.debug("opened session at timestamp: " + timestamp);
                }
            }

            public Session getSession(EntityMode entityMode) {
                if (this .entityMode == entityMode) {
                    return this ;
                }

                if (rootSession != null) {
                    return rootSession.getSession(entityMode);
                }

                errorIfClosed();
                checkTransactionSynchStatus();

                SessionImpl rtn = null;
                if (childSessionsByEntityMode == null) {
                    childSessionsByEntityMode = new HashMap();
                } else {
                    rtn = (SessionImpl) childSessionsByEntityMode
                            .get(entityMode);
                }

                if (rtn == null) {
                    rtn = new SessionImpl(this , entityMode);
                    childSessionsByEntityMode.put(entityMode, rtn);
                }

                return rtn;
            }

            public void clear() {
                errorIfClosed();
                checkTransactionSynchStatus();
                persistenceContext.clear();
                actionQueue.clear();
            }

            public Batcher getBatcher() {
                errorIfClosed();
                checkTransactionSynchStatus();
                // TODO : should remove this exposure
                //  and have all references to the session's batcher use the ConnectionManager.
                return jdbcContext.getConnectionManager().getBatcher();
            }

            public long getTimestamp() {
                checkTransactionSynchStatus();
                return timestamp;
            }

            public Connection close() throws HibernateException {
                log.trace("closing session");
                if (isClosed()) {
                    throw new SessionException("Session was already closed");
                }

                if (factory.getStatistics().isStatisticsEnabled()) {
                    factory.getStatisticsImplementor().closeSession();
                }

                try {
                    try {
                        if (childSessionsByEntityMode != null) {
                            Iterator childSessions = childSessionsByEntityMode
                                    .values().iterator();
                            while (childSessions.hasNext()) {
                                final SessionImpl child = (SessionImpl) childSessions
                                        .next();
                                child.close();
                            }
                        }
                    } catch (Throwable t) {
                        // just ignore
                    }

                    if (rootSession == null) {
                        return jdbcContext.getConnectionManager().close();
                    } else {
                        return null;
                    }
                } finally {
                    setClosed();
                    cleanup();
                }
            }

            public ConnectionReleaseMode getConnectionReleaseMode() {
                checkTransactionSynchStatus();
                return connectionReleaseMode;
            }

            public boolean isAutoCloseSessionEnabled() {
                return autoCloseSessionEnabled;
            }

            public boolean isOpen() {
                checkTransactionSynchStatus();
                return !isClosed();
            }

            public boolean isFlushModeNever() {
                return FlushMode.isManualFlushMode(getFlushMode());
            }

            public boolean isFlushBeforeCompletionEnabled() {
                return flushBeforeCompletionEnabled;
            }

            public void managedFlush() {
                if (isClosed()) {
                    log.trace("skipping auto-flush due to session closed");
                    return;
                }
                log.trace("automatically flushing session");
                flush();

                if (childSessionsByEntityMode != null) {
                    Iterator iter = childSessionsByEntityMode.values()
                            .iterator();
                    while (iter.hasNext()) {
                        ((Session) iter.next()).flush();
                    }
                }
            }

            /**
             * Return changes to this session and its child sessions that have not been flushed yet.
             * <p/>
             * @return The non-flushed changes.
             */
            public NonFlushedChanges getNonFlushedChanges()
                    throws HibernateException {
                errorIfClosed();
                checkTransactionSynchStatus();
                NonFlushedChanges nonFlushedChanges = new NonFlushedChangesImpl(
                        this );
                if (childSessionsByEntityMode != null) {
                    Iterator it = childSessionsByEntityMode.values().iterator();
                    while (it.hasNext()) {
                        nonFlushedChanges.extractFromSession((EventSource) it
                                .next());
                    }
                }
                return nonFlushedChanges;
            }

            /**
             * Apply non-flushed changes from a different session to this session. It is assumed
             * that this SessionImpl is "clean" (e.g., has no non-flushed changes, no cached entities,
             * no cached collections, no queued actions). The specified NonFlushedChanges object cannot
             * be bound to any session.
             * <p/>
             * @param nonFlushedChanges the non-flushed changes
             */
            public void applyNonFlushedChanges(
                    NonFlushedChanges nonFlushedChanges)
                    throws HibernateException {
                errorIfClosed();
                checkTransactionSynchStatus();
                replacePersistenceContext(((NonFlushedChangesImpl) nonFlushedChanges)
                        .getPersistenceContext(entityMode));
                replaceActionQueue(((NonFlushedChangesImpl) nonFlushedChanges)
                        .getActionQueue(entityMode));
                if (childSessionsByEntityMode != null) {
                    for (Iterator it = childSessionsByEntityMode.values()
                            .iterator(); it.hasNext();) {
                        ((SessionImpl) it.next())
                                .applyNonFlushedChanges(nonFlushedChanges);
                    }
                }
            }

            private void replacePersistenceContext(
                    StatefulPersistenceContext persistenceContextNew) {
                if (persistenceContextNew.getSession() != null) {
                    throw new IllegalStateException(
                            "new persistence context is already connected to a session ");
                }
                persistenceContext.clear();
                ObjectInputStream ois = null;
                try {
                    ois = new ObjectInputStream(new ByteArrayInputStream(
                            serializePersistenceContext(persistenceContextNew)));
                    this .persistenceContext = StatefulPersistenceContext
                            .deserialize(ois, this );
                } catch (IOException ex) {
                    throw new SerializationException(
                            "could not deserialize the persistence context", ex);
                } catch (ClassNotFoundException ex) {
                    throw new SerializationException(
                            "could not deserialize the persistence context", ex);
                } finally {
                    try {
                        if (ois != null)
                            ois.close();
                    } catch (IOException ex) {
                    }
                }
            }

            private static byte[] serializePersistenceContext(
                    StatefulPersistenceContext pc) {
                ByteArrayOutputStream baos = new ByteArrayOutputStream(512);
                ObjectOutputStream oos = null;
                try {
                    oos = new ObjectOutputStream(baos);
                    ((StatefulPersistenceContext) pc).serialize(oos);
                } catch (IOException ex) {
                    throw new SerializationException(
                            "could not serialize persistence context", ex);
                } finally {
                    if (oos != null) {
                        try {
                            oos.close();
                        } catch (IOException ex) {
                            //ignore
                        }
                    }
                }
                return baos.toByteArray();
            }

            private void replaceActionQueue(ActionQueue actionQueueNew) {
                if (actionQueue.hasAnyQueuedActions()) {
                    throw new IllegalStateException(
                            "cannot replace an ActionQueue with queued actions ");
                }
                actionQueue.clear();
                ObjectInputStream ois = null;
                try {
                    ois = new ObjectInputStream(new ByteArrayInputStream(
                            serializeActionQueue(actionQueueNew)));
                    actionQueue = ActionQueue.deserialize(ois, this );
                } catch (IOException ex) {
                    throw new SerializationException(
                            "could not deserialize the action queue", ex);
                } catch (ClassNotFoundException ex) {
                    throw new SerializationException(
                            "could not deserialize the action queue", ex);
                } finally {
                    try {
                        if (ois != null)
                            ois.close();
                    } catch (IOException ex) {
                    }
                }
            }

            private static byte[] serializeActionQueue(ActionQueue actionQueue) {
                ByteArrayOutputStream baos = new ByteArrayOutputStream(512);
                ObjectOutputStream oos = null;
                try {
                    oos = new ObjectOutputStream(baos);
                    actionQueue.serialize(oos);
                } catch (IOException ex) {
                    throw new SerializationException(
                            "could not serialize action queue", ex);
                } finally {
                    if (oos != null) {
                        try {
                            oos.close();
                        } catch (IOException ex) {
                            //ignore
                        }
                    }
                }
                return baos.toByteArray();
            }

            public boolean shouldAutoClose() {
                return isAutoCloseSessionEnabled() && !isClosed();
            }

            public void managedClose() {
                log.trace("automatically closing session");
                close();
            }

            public Connection connection() throws HibernateException {
                errorIfClosed();
                return jdbcContext.borrowConnection();
            }

            public boolean isConnected() {
                checkTransactionSynchStatus();
                return !isClosed()
                        && jdbcContext.getConnectionManager()
                                .isCurrentlyConnected();
            }

            public boolean isTransactionInProgress() {
                checkTransactionSynchStatus();
                return !isClosed() && jdbcContext.isTransactionInProgress();
            }

            public Connection disconnect() throws HibernateException {
                errorIfClosed();
                log.debug("disconnecting session");
                return jdbcContext.getConnectionManager().manualDisconnect();
            }

            public void reconnect() throws HibernateException {
                errorIfClosed();
                log.debug("reconnecting session");
                checkTransactionSynchStatus();
                jdbcContext.getConnectionManager().manualReconnect();
            }

            public void reconnect(Connection conn) throws HibernateException {
                errorIfClosed();
                log.debug("reconnecting session");
                checkTransactionSynchStatus();
                jdbcContext.getConnectionManager().manualReconnect(conn);
            }

            public void beforeTransactionCompletion(Transaction tx) {
                log.trace("before transaction completion");
                actionQueue.beforeTransactionCompletion();
                if (rootSession == null) {
                    try {
                        interceptor.beforeTransactionCompletion(tx);
                    } catch (Throwable t) {
                        log
                                .error(
                                        "exception in interceptor beforeTransactionCompletion()",
                                        t);
                    }
                }
            }

            public void setAutoClear(boolean enabled) {
                errorIfClosed();
                autoClear = enabled;
            }

            /**
             * Check if there is a Hibernate or JTA transaction in progress and, 
             * if there is not, flush if necessary, make sure the connection has 
             * been committed (if it is not in autocommit mode) and run the after 
             * completion processing
             */
            public void afterOperation(boolean success) {
                if (!jdbcContext.isTransactionInProgress()) {
                    jdbcContext.afterNontransactionalQuery(success);
                }
            }

            public void afterTransactionCompletion(boolean success,
                    Transaction tx) {
                log.trace("after transaction completion");
                persistenceContext.afterTransactionCompletion();
                actionQueue.afterTransactionCompletion(success);
                if (rootSession == null && tx != null) {
                    try {
                        interceptor.afterTransactionCompletion(tx);
                    } catch (Throwable t) {
                        log
                                .error(
                                        "exception in interceptor afterTransactionCompletion()",
                                        t);
                    }
                }
                if (autoClear) {
                    clear();
                }
            }

            /**
             * clear all the internal collections, just 
             * to help the garbage collector, does not
             * clear anything that is needed during the
             * afterTransactionCompletion() phase
             */
            private void cleanup() {
                persistenceContext.clear();
            }

            public LockMode getCurrentLockMode(Object object)
                    throws HibernateException {
                errorIfClosed();
                checkTransactionSynchStatus();
                if (object == null) {
                    throw new NullPointerException(
                            "null object passed to getCurrentLockMode()");
                }
                if (object instanceof  HibernateProxy) {
                    object = ((HibernateProxy) object)
                            .getHibernateLazyInitializer().getImplementation(
                                    this );
                    if (object == null) {
                        return LockMode.NONE;
                    }
                }
                EntityEntry e = persistenceContext.getEntry(object);
                if (e == null) {
                    throw new TransientObjectException(
                            "Given object not associated with the session");
                }
                if (e.getStatus() != Status.MANAGED) {
                    throw new ObjectDeletedException(
                            "The given object was deleted", e.getId(), e
                                    .getPersister().getEntityName());
                }
                return e.getLockMode();
            }

            public Object getEntityUsingInterceptor(EntityKey key)
                    throws HibernateException {
                errorIfClosed();
                // todo : should this get moved to PersistentContext?
                // logically, is PersistentContext the "thing" to which an interceptor gets attached?
                final Object result = persistenceContext.getEntity(key);
                if (result == null) {
                    final Object newObject = interceptor.getEntity(key
                            .getEntityName(), key.getIdentifier());
                    if (newObject != null) {
                        lock(newObject, LockMode.NONE);
                    }
                    return newObject;
                } else {
                    return result;
                }
            }

            // saveOrUpdate() operations ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

            public void saveOrUpdate(Object object) throws HibernateException {
                saveOrUpdate(null, object);
            }

            public void saveOrUpdate(String entityName, Object obj)
                    throws HibernateException {
                fireSaveOrUpdate(new SaveOrUpdateEvent(entityName, obj, this ));
            }

            private void fireSaveOrUpdate(SaveOrUpdateEvent event) {
                errorIfClosed();
                checkTransactionSynchStatus();
                SaveOrUpdateEventListener[] saveOrUpdateEventListener = listeners
                        .getSaveOrUpdateEventListeners();
                for (int i = 0; i < saveOrUpdateEventListener.length; i++) {
                    saveOrUpdateEventListener[i].onSaveOrUpdate(event);
                }
            }

            // save() operations ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

            public void save(Object obj, Serializable id)
                    throws HibernateException {
                save(null, obj, id);
            }

            public Serializable save(Object obj) throws HibernateException {
                return save(null, obj);
            }

            public Serializable save(String entityName, Object object)
                    throws HibernateException {
                return fireSave(new SaveOrUpdateEvent(entityName, object, this ));
            }

            public void save(String entityName, Object object, Serializable id)
                    throws HibernateException {
                fireSave(new SaveOrUpdateEvent(entityName, object, id, this ));
            }

            private Serializable fireSave(SaveOrUpdateEvent event) {
                errorIfClosed();
                checkTransactionSynchStatus();
                SaveOrUpdateEventListener[] saveEventListener = listeners
                        .getSaveEventListeners();
                for (int i = 0; i < saveEventListener.length; i++) {
                    saveEventListener[i].onSaveOrUpdate(event);
                }
                return event.getResultId();
            }

            // update() operations ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

            public void update(Object obj) throws HibernateException {
                update(null, obj);
            }

            public void update(Object obj, Serializable id)
                    throws HibernateException {
                update(null, obj, id);
            }

            public void update(String entityName, Object object)
                    throws HibernateException {
                fireUpdate(new SaveOrUpdateEvent(entityName, object, this ));
            }

            public void update(String entityName, Object object, Serializable id)
                    throws HibernateException {
                fireUpdate(new SaveOrUpdateEvent(entityName, object, id, this ));
            }

            private void fireUpdate(SaveOrUpdateEvent event) {
                errorIfClosed();
                checkTransactionSynchStatus();
                SaveOrUpdateEventListener[] updateEventListener = listeners
                        .getUpdateEventListeners();
                for (int i = 0; i < updateEventListener.length; i++) {
                    updateEventListener[i].onSaveOrUpdate(event);
                }
            }

            // lock() operations ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

            public void lock(String entityName, Object object, LockMode lockMode)
                    throws HibernateException {
                fireLock(new LockEvent(entityName, object, lockMode, this ));
            }

            public LockRequest buildLockRequest(LockOptions lockOptions) {
                return new LockRequestImpl(lockOptions);
            }

            public void lock(Object object, LockMode lockMode)
                    throws HibernateException {
                fireLock(new LockEvent(object, lockMode, this ));
            }

            private void fireLock(String entityName, Object object,
                    LockOptions options) {
                fireLock(new LockEvent(entityName, object, options, this ));
            }

            private void fireLock(Object object, LockOptions options) {
                fireLock(new LockEvent(object, options, this ));
            }

            private void fireLock(LockEvent lockEvent) {
                errorIfClosed();
                checkTransactionSynchStatus();
                LockEventListener[] lockEventListener = listeners
                        .getLockEventListeners();
                for (int i = 0; i < lockEventListener.length; i++) {
                    lockEventListener[i].onLock(lockEvent);
                }
            }

            // persist() operations ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

            public void persist(String entityName, Object object)
                    throws HibernateException {
                firePersist(new PersistEvent(entityName, object, this ));
            }

            public void persist(Object object) throws HibernateException {
                persist(null, object);
            }

            public void persist(String entityName, Object object,
                    Map copiedAlready) throws HibernateException {
                firePersist(copiedAlready, new PersistEvent(entityName, object,
                        this ));
            }

            private void firePersist(Map copiedAlready, PersistEvent event) {
                errorIfClosed();
                checkTransactionSynchStatus();
                PersistEventListener[] persistEventListener = listeners
                        .getPersistEventListeners();
                for (int i = 0; i < persistEventListener.length; i++) {
                    persistEventListener[i].onPersist(event, copiedAlready);
                }
            }

            private void firePersist(PersistEvent event) {
                errorIfClosed();
                checkTransactionSynchStatus();
                PersistEventListener[] createEventListener = listeners
                        .getPersistEventListeners();
                for (int i = 0; i < createEventListener.length; i++) {
                    createEventListener[i].onPersist(event);
                }
            }

            // persistOnFlush() operations ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

            public void persistOnFlush(String entityName, Object object)
                    throws HibernateException {
                firePersistOnFlush(new PersistEvent(entityName, object, this ));
            }

            public void persistOnFlush(Object object) throws HibernateException {
                persist(null, object);
            }

            public void persistOnFlush(String entityName, Object object,
                    Map copiedAlready) throws HibernateException {
                firePersistOnFlush(copiedAlready, new PersistEvent(entityName,
                        object, this ));
            }

            private void firePersistOnFlush(Map copiedAlready,
                    PersistEvent event) {
                errorIfClosed();
                checkTransactionSynchStatus();
                PersistEventListener[] persistEventListener = listeners
                        .getPersistOnFlushEventListeners();
                for (int i = 0; i < persistEventListener.length; i++) {
                    persistEventListener[i].onPersist(event, copiedAlready);
                }
            }

            private void firePersistOnFlush(PersistEvent event) {
                errorIfClosed();
                checkTransactionSynchStatus();
                PersistEventListener[] createEventListener = listeners
                        .getPersistOnFlushEventListeners();
                for (int i = 0; i < createEventListener.length; i++) {
                    createEventListener[i].onPersist(event);
                }
            }

            // merge() operations ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

            public Object merge(String entityName, Object object)
                    throws HibernateException {
                return fireMerge(new MergeEvent(entityName, object, this ));
            }

            public Object merge(Object object) throws HibernateException {
                return merge(null, object);
            }

            public void merge(String entityName, Object object,
                    Map copiedAlready) throws HibernateException {
                fireMerge(copiedAlready, new MergeEvent(entityName, object,
                        this ));
            }

            private Object fireMerge(MergeEvent event) {
                errorIfClosed();
                checkTransactionSynchStatus();
                MergeEventListener[] mergeEventListener = listeners
                        .getMergeEventListeners();
                for (int i = 0; i < mergeEventListener.length; i++) {
                    mergeEventListener[i].onMerge(event);
                }
                return event.getResult();
            }

            private void fireMerge(Map copiedAlready, MergeEvent event) {
                errorIfClosed();
                checkTransactionSynchStatus();
                MergeEventListener[] mergeEventListener = listeners
                        .getMergeEventListeners();
                for (int i = 0; i < mergeEventListener.length; i++) {
                    mergeEventListener[i].onMerge(event, copiedAlready);
                }
            }

            // saveOrUpdateCopy() operations ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

            public Object saveOrUpdateCopy(String entityName, Object object)
                    throws HibernateException {
                return fireSaveOrUpdateCopy(new MergeEvent(entityName, object,
                        this ));
            }

            public Object saveOrUpdateCopy(Object object)
                    throws HibernateException {
                return saveOrUpdateCopy(null, object);
            }

            public Object saveOrUpdateCopy(String entityName, Object object,
                    Serializable id) throws HibernateException {
                return fireSaveOrUpdateCopy(new MergeEvent(entityName, object,
                        id, this ));
            }

            public Object saveOrUpdateCopy(Object object, Serializable id)
                    throws HibernateException {
                return saveOrUpdateCopy(null, object, id);
            }

            public void saveOrUpdateCopy(String entityName, Object object,
                    Map copiedAlready) throws HibernateException {
                fireSaveOrUpdateCopy(copiedAlready, new MergeEvent(entityName,
                        object, this ));
            }

            private void fireSaveOrUpdateCopy(Map copiedAlready,
                    MergeEvent event) {
                errorIfClosed();
                checkTransactionSynchStatus();
                MergeEventListener[] saveOrUpdateCopyEventListener = listeners
                        .getSaveOrUpdateCopyEventListeners();
                for (int i = 0; i < saveOrUpdateCopyEventListener.length; i++) {
                    saveOrUpdateCopyEventListener[i].onMerge(event,
                            copiedAlready);
                }
            }

            private Object fireSaveOrUpdateCopy(MergeEvent event) {
                errorIfClosed();
                checkTransactionSynchStatus();
                MergeEventListener[] saveOrUpdateCopyEventListener = listeners
                        .getSaveOrUpdateCopyEventListeners();
                for (int i = 0; i < saveOrUpdateCopyEventListener.length; i++) {
                    saveOrUpdateCopyEventListener[i].onMerge(event);
                }
                return event.getResult();
            }

            // delete() operations ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

            /**
             * Delete a persistent object
             */
            public void delete(Object object) throws HibernateException {
                fireDelete(new DeleteEvent(object, this ));
            }

            /**
             * Delete a persistent object (by explicit entity name)
             */
            public void delete(String entityName, Object object)
                    throws HibernateException {
                fireDelete(new DeleteEvent(entityName, object, this ));
            }

            /**
             * Delete a persistent object
             */
            public void delete(String entityName, Object object,
                    boolean isCascadeDeleteEnabled, Set transientEntities)
                    throws HibernateException {
                fireDelete(new DeleteEvent(entityName, object,
                        isCascadeDeleteEnabled, this ), transientEntities);
            }

            private void fireDelete(DeleteEvent event) {
                errorIfClosed();
                checkTransactionSynchStatus();
                DeleteEventListener[] deleteEventListener = listeners
                        .getDeleteEventListeners();
                for (int i = 0; i < deleteEventListener.length; i++) {
                    deleteEventListener[i].onDelete(event);
                }
            }

            private void fireDelete(DeleteEvent event, Set transientEntities) {
                errorIfClosed();
                checkTransactionSynchStatus();
                DeleteEventListener[] deleteEventListener = listeners
                        .getDeleteEventListeners();
                for (int i = 0; i < deleteEventListener.length; i++) {
                    deleteEventListener[i].onDelete(event, transientEntities);
                }
            }

            // load()/get() operations ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

            public void load(Object object, Serializable id)
                    throws HibernateException {
                LoadEvent event = new LoadEvent(id, object, this );
                fireLoad(event, LoadEventListener.RELOAD);
            }

            public Object load(Class entityClass, Serializable id)
                    throws HibernateException {
                return load(entityClass.getName(), id);
            }

            public Object load(String entityName, Serializable id)
                    throws HibernateException {
                LoadEvent event = new LoadEvent(id, entityName, false, this );
                boolean success = false;
                try {
                    fireLoad(event, LoadEventListener.LOAD);
                    if (event.getResult() == null) {
                        getFactory().getEntityNotFoundDelegate()
                                .handleEntityNotFound(entityName, id);
                    }
                    success = true;
                    return event.getResult();
                } finally {
                    afterOperation(success);
                }
            }

            public Object get(Class entityClass, Serializable id)
                    throws HibernateException {
                return get(entityClass.getName(), id);
            }

            public Object get(String entityName, Serializable id)
                    throws HibernateException {
                LoadEvent event = new LoadEvent(id, entityName, false, this );
                boolean success = false;
                try {
                    fireLoad(event, LoadEventListener.GET);
                    success = true;
                    return event.getResult();
                } finally {
                    afterOperation(success);
                }
            }

            /**
             * Load the data for the object with the specified id into a newly created object.
             * This is only called when lazily initializing a proxy.
             * Do NOT return a proxy.
             */
            public Object immediateLoad(String entityName, Serializable id)
                    throws HibernateException {
                if (log.isDebugEnabled()) {
                    EntityPersister persister = getFactory()
                            .getEntityPersister(entityName);
                    log.debug("initializing proxy: "
                            + MessageHelper.infoString(persister, id,
                                    getFactory()));
                }

                LoadEvent event = new LoadEvent(id, entityName, true, this );
                fireLoad(event, LoadEventListener.IMMEDIATE_LOAD);
                return event.getResult();
            }

            public Object internalLoad(String entityName, Serializable id,
                    boolean eager, boolean nullable) throws HibernateException {
                // todo : remove
                LoadEventListener.LoadType type = nullable ? LoadEventListener.INTERNAL_LOAD_NULLABLE
                        : eager ? LoadEventListener.INTERNAL_LOAD_EAGER
                                : LoadEventListener.INTERNAL_LOAD_LAZY;
                LoadEvent event = new LoadEvent(id, entityName, true, this );
                fireLoad(event, type);
                if (!nullable) {
                    UnresolvableObjectException.throwIfNull(event.getResult(),
                            id, entityName);
                }
                return event.getResult();
            }

            public Object load(Class entityClass, Serializable id,
                    LockMode lockMode) throws HibernateException {
                return load(entityClass.getName(), id, lockMode);
            }

            public Object load(Class entityClass, Serializable id,
                    LockOptions lockOptions) throws HibernateException {
                return load(entityClass.getName(), id, lockOptions);
            }

            public Object load(String entityName, Serializable id,
                    LockMode lockMode) throws HibernateException {
                LoadEvent event = new LoadEvent(id, entityName, lockMode, this );
                fireLoad(event, LoadEventListener.LOAD);
                return event.getResult();
            }

            public Object load(String entityName, Serializable id,
                    LockOptions lockOptions) throws HibernateException {
                LoadEvent event = new LoadEvent(id, entityName, lockOptions,
                        this );
                fireLoad(event, LoadEventListener.LOAD);
                return event.getResult();
            }

            public Object get(Class entityClass, Serializable id,
                    LockMode lockMode) throws HibernateException {
                return get(entityClass.getName(), id, lockMode);
            }

            public Object get(Class entityClass, Serializable id,
                    LockOptions lockOptions) throws HibernateException {
                return get(entityClass.getName(), id, lockOptions);
            }

            public Object get(String entityName, Serializable id,
                    LockMode lockMode) throws HibernateException {
                LoadEvent event = new LoadEvent(id, entityName, lockMode, this );
                fireLoad(event, LoadEventListener.GET);
                return event.getResult();
            }

            public Object get(String entityName, Serializable id,
                    LockOptions lockOptions) throws HibernateException {
                LoadEvent event = new LoadEvent(id, entityName, lockOptions,
                        this );
                fireLoad(event, LoadEventListener.GET);
                return event.getResult();
            }

            private void fireLoad(LoadEvent event, LoadType loadType) {
                errorIfClosed();
                checkTransactionSynchStatus();
                LoadEventListener[] loadEventListener = listeners
                        .getLoadEventListeners();
                for (int i = 0; i < loadEventListener.length; i++) {
                    loadEventListener[i].onLoad(event, loadType);
                }
            }

            // refresh() operations ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

            public void refresh(Object object) throws HibernateException {
                fireRefresh(new RefreshEvent(object, this ));
            }

            public void refresh(Object object, LockMode lockMode)
                    throws HibernateException {
                fireRefresh(new RefreshEvent(object, lockMode, this ));
            }

            public void refresh(Object object, LockOptions lockOptions)
                    throws HibernateException {
                fireRefresh(new RefreshEvent(object, lockOptions, this ));
            }

            public void refresh(Object object, Map refreshedAlready)
                    throws HibernateException {
                fireRefresh(refreshedAlready, new RefreshEvent(object, this ));
            }

            private void fireRefresh(RefreshEvent refreshEvent) {
                errorIfClosed();
                checkTransactionSynchStatus();
                RefreshEventListener[] refreshEventListener = listeners
                        .getRefreshEventListeners();
                for (int i = 0; i < refreshEventListener.length; i++) {
                    refreshEventListener[i].onRefresh(refreshEvent);
                }
            }

            private void fireRefresh(Map refreshedAlready,
                    RefreshEvent refreshEvent) {
                errorIfClosed();
                checkTransactionSynchStatus();
                RefreshEventListener[] refreshEventListener = listeners
                        .getRefreshEventListeners();
                for (int i = 0; i < refreshEventListener.length; i++) {
                    refreshEventListener[i].onRefresh(refreshEvent,
                            refreshedAlready);
                }
            }

            // replicate() operations ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

            public void replicate(Object obj, ReplicationMode replicationMode)
                    throws HibernateException {
                fireReplicate(new ReplicateEvent(obj, replicationMode, this ));
            }

            public void replicate(String entityName, Object obj,
                    ReplicationMode replicationMode) throws HibernateException {
                fireReplicate(new ReplicateEvent(entityName, obj,
                        replicationMode, this ));
            }

            private void fireReplicate(ReplicateEvent event) {
                errorIfClosed();
                checkTransactionSynchStatus();
                ReplicateEventListener[] replicateEventListener = listeners
                        .getReplicateEventListeners();
                for (int i = 0; i < replicateEventListener.length; i++) {
                    replicateEventListener[i].onReplicate(event);
                }
            }

            // evict() operations ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

            /**
             * remove any hard references to the entity that are held by the infrastructure
             * (references held by application or other persistant instances are okay)
             */
            public void evict(Object object) throws HibernateException {
                fireEvict(new EvictEvent(object, this ));
            }

            private void fireEvict(EvictEvent evictEvent) {
                errorIfClosed();
                checkTransactionSynchStatus();
                EvictEventListener[] evictEventListener = listeners
                        .getEvictEventListeners();
                for (int i = 0; i < evictEventListener.length; i++) {
                    evictEventListener[i].onEvict(evictEvent);
                }
            }

            /**
             * detect in-memory changes, determine if the changes are to tables
             * named in the query and, if so, complete execution the flush
             */
            protected boolean autoFlushIfRequired(Set querySpaces)
                    throws HibernateException {
                errorIfClosed();
                if (!isTransactionInProgress()) {
                    // do not auto-flush while outside a transaction
                    return false;
                }
                AutoFlushEvent event = new AutoFlushEvent(querySpaces, this );
                AutoFlushEventListener[] autoFlushEventListener = listeners
                        .getAutoFlushEventListeners();
                for (int i = 0; i < autoFlushEventListener.length; i++) {
                    autoFlushEventListener[i].onAutoFlush(event);
                }
                return event.isFlushRequired();
            }

            public boolean isDirty() throws HibernateException {
                errorIfClosed();
                checkTransactionSynchStatus();
                log.debug("checking session dirtiness");
                if (actionQueue.areInsertionsOrDeletionsQueued()) {
                    log
                            .debug("session dirty (scheduled updates and insertions)");
                    return true;
                } else {
                    DirtyCheckEvent event = new DirtyCheckEvent(this );
                    DirtyCheckEventListener[] dirtyCheckEventListener = listeners
                            .getDirtyCheckEventListeners();
                    for (int i = 0; i < dirtyCheckEventListener.length; i++) {
                        dirtyCheckEventListener[i].onDirtyCheck(event);
                    }
                    return event.isDirty();
                }
            }

            public void flush() throws HibernateException {
                errorIfClosed();
                checkTransactionSynchStatus();
                if (persistenceContext.getCascadeLevel() > 0) {
                    throw new HibernateException(
                            "Flush during cascade is dangerous");
                }
                FlushEventListener[] flushEventListener = listeners
                        .getFlushEventListeners();
                for (int i = 0; i < flushEventListener.length; i++) {
                    flushEventListener[i].onFlush(new FlushEvent(this ));
                }
            }

            public void forceFlush(EntityEntry entityEntry)
                    throws HibernateException {
                errorIfClosed();
                if (log.isDebugEnabled()) {
                    log.debug("flushing to force deletion of re-saved object: "
                            + MessageHelper.infoString(entityEntry
                                    .getPersister(), entityEntry.getId(),
                                    getFactory()));
                }

                if (persistenceContext.getCascadeLevel() > 0) {
                    throw new ObjectDeletedException(
                            "deleted object would be re-saved by cascade (remove deleted object from associations)",
                            entityEntry.getId(), entityEntry.getPersister()
                                    .getEntityName());
                }

                flush();
            }

            /**
             * Retrieve a list of persistent objects using a hibernate query
             */
            public List find(String query) throws HibernateException {
                return list(query, new QueryParameters());
            }

            public List find(String query, Object value, Type type)
                    throws HibernateException {
                return list(query, new QueryParameters(type, value));
            }

            public List find(String query, Object[] values, Type[] types)
                    throws HibernateException {
                return list(query, new QueryParameters(types, values));
            }

            public List list(String query, QueryParameters queryParameters)
                    throws HibernateException {
                errorIfClosed();
                checkTransactionSynchStatus();
                queryParameters.validateParameters();
                HQLQueryPlan plan = getHQLQueryPlan(query, false);
                autoFlushIfRequired(plan.getQuerySpaces());

                List results = CollectionHelper.EMPTY_LIST;
                boolean success = false;

                dontFlushFromFind++; //stops flush being called multiple times if this method is recursively called
                try {
                    results = plan.performList(queryParameters, this );
                    success = true;
                } finally {
                    dontFlushFromFind--;
                    afterOperation(success);
                }
                return results;
            }

            public int executeUpdate(String query,
                    QueryParameters queryParameters) throws HibernateException {
                errorIfClosed();
                checkTransactionSynchStatus();
                queryParameters.validateParameters();
                HQLQueryPlan plan = getHQLQueryPlan(query, false);
                autoFlushIfRequired(plan.getQuerySpaces());

                boolean success = false;
                int result = 0;
                try {
                    result = plan.performExecuteUpdate(queryParameters, this );
                    success = true;
                } finally {
                    afterOperation(success);
                }
                return result;
            }

            public int executeNativeUpdate(
                    NativeSQLQuerySpecification nativeQuerySpecification,
                    QueryParameters queryParameters) throws HibernateException {
                errorIfClosed();
                checkTransactionSynchStatus();
                queryParameters.validateParameters();
                NativeSQLQueryPlan plan = getNativeSQLQueryPlan(nativeQuerySpecification);

                autoFlushIfRequired(plan.getCustomQuery().getQuerySpaces());

                boolean success = false;
                int result = 0;
                try {
                    result = plan.performExecuteUpdate(queryParameters, this );
                    success = true;
                } finally {
                    afterOperation(success);
                }
                return result;
            }

            public Iterator iterate(String query) throws HibernateException {
                return iterate(query, new QueryParameters());
            }

            public Iterator iterate(String query, Object value, Type type)
                    throws HibernateException {
                return iterate(query, new QueryParameters(type, value));
            }

            public Iterator iterate(String query, Object[] values, Type[] types)
                    throws HibernateException {
                return iterate(query, new QueryParameters(types, values));
            }

            public Iterator iterate(String query,
                    QueryParameters queryParameters) throws HibernateException {
                errorIfClosed();
                checkTransactionSynchStatus();
                queryParameters.validateParameters();
                HQLQueryPlan plan = getHQLQueryPlan(query, true);
                autoFlushIfRequired(plan.getQuerySpaces());

                dontFlushFromFind++; //stops flush being called multiple times if this method is recursively called
                try {
                    return plan.performIterate(queryParameters, this );
                } finally {
                    dontFlushFromFind--;
                }
            }

            public ScrollableResults scroll(String query,
                    QueryParameters queryParameters) throws HibernateException {
                errorIfClosed();
                checkTransactionSynchStatus();
                HQLQueryPlan plan = getHQLQueryPlan(query, false);
                autoFlushIfRequired(plan.getQuerySpaces());
                dontFlushFromFind++;
                try {
                    return plan.performScroll(queryParameters, this );
                } finally {
                    dontFlushFromFind--;
                }
            }

            public int delete(String query) throws HibernateException {
                return delete(query, ArrayHelper.EMPTY_OBJECT_ARRAY,
                        ArrayHelper.EMPTY_TYPE_ARRAY);
            }

            public int delete(String query, Object value, Type type)
                    throws HibernateException {
                return delete(query, new Object[] { value },
                        new Type[] { type });
            }

            public int delete(String query, Object[] values, Type[] types)
                    throws HibernateException {
                errorIfClosed();
                checkTransactionSynchStatus();
                if (query == null) {
                    throw new IllegalArgumentException(
                            "attempt to doAfterTransactionCompletion delete-by-query with null query");
                }

                if (log.isTraceEnabled()) {
                    log.trace("delete: " + query);
                    if (values.length != 0) {
                        log.trace("parameters: "
                                + StringHelper.toString(values));
                    }
                }

                List list = find(query, values, types);
                int deletionCount = list.size();
                for (int i = 0; i < deletionCount; i++) {
                    delete(list.get(i));
                }

                return deletionCount;
            }

            public Query createFilter(Object collection, String queryString) {
                errorIfClosed();
                checkTransactionSynchStatus();
                CollectionFilterImpl filter = new CollectionFilterImpl(
                        queryString, collection, this , getFilterQueryPlan(
                                collection, queryString, null, false)
                                .getParameterMetadata());
                filter.setComment(queryString);
                return filter;
            }

            public Query getNamedQuery(String queryName)
                    throws MappingException {
                errorIfClosed();
                checkTransactionSynchStatus();
                return super .getNamedQuery(queryName);
            }

            public Object instantiate(String entityName, Serializable id)
                    throws HibernateException {
                return instantiate(factory.getEntityPersister(entityName), id);
            }

            /**
             * give the interceptor an opportunity to override the default instantiation
             */
            public Object instantiate(EntityPersister persister, Serializable id)
                    throws HibernateException {
                errorIfClosed();
                checkTransactionSynchStatus();
                Object result = interceptor.instantiate(persister
                        .getEntityName(), entityMode, id);
                if (result == null) {
                    result = persister.instantiate(id, entityMode);
                }
                return result;
            }

            public EntityMode getEntityMode() {
                checkTransactionSynchStatus();
                return entityMode;
            }

            public void setFlushMode(FlushMode flushMode) {
                errorIfClosed();
                checkTransactionSynchStatus();
                if (log.isTraceEnabled()) {
                    log.trace("setting flush mode to: " + flushMode);
                }
                this .flushMode = flushMode;
            }

            public FlushMode getFlushMode() {
                checkTransactionSynchStatus();
                return flushMode;
            }

            public CacheMode getCacheMode() {
                checkTransactionSynchStatus();
                return cacheMode;
            }

            public void setCacheMode(CacheMode cacheMode) {
                errorIfClosed();
                checkTransactionSynchStatus();
                if (log.isTraceEnabled()) {
                    log.trace("setting cache mode to: " + cacheMode);
                }
                this .cacheMode = cacheMode;
            }

            public Transaction getTransaction() throws HibernateException {
                errorIfClosed();
                return jdbcContext.getTransaction();
            }

            public Transaction beginTransaction() throws HibernateException {
                errorIfClosed();
                if (rootSession != null) {
                    // todo : should seriously consider not allowing a txn to begin from a child session
                    //      can always route the request to the root session...
                    log.warn("Transaction started on non-root session");
                }
                Transaction result = getTransaction();
                result.begin();
                return result;
            }

            public void afterTransactionBegin(Transaction tx) {
                errorIfClosed();
                interceptor.afterTransactionBegin(tx);
            }

            public EntityPersister getEntityPersister(final String entityName,
                    final Object object) {
                errorIfClosed();
                if (entityName == null) {
                    return factory.getEntityPersister(guessEntityName(object));
                } else {
                    // try block is a hack around fact that currently tuplizers are not
                    // given the opportunity to resolve a subclass entity name.  this
                    // allows the (we assume custom) interceptor the ability to
                    // influence this decision if we were not able to based on the
                    // given entityName
                    try {
                        return factory.getEntityPersister(entityName)
                                .getSubclassEntityPersister(object,
                                        getFactory(), entityMode);
                    } catch (HibernateException e) {
                        try {
                            return getEntityPersister(null, object);
                        } catch (HibernateException e2) {
                            throw e;
                        }
                    }
                }
            }

            // not for internal use:
            public Serializable getIdentifier(Object object)
                    throws HibernateException {
                errorIfClosed();
                checkTransactionSynchStatus();
                if (object instanceof  HibernateProxy) {
                    LazyInitializer li = ((HibernateProxy) object)
                            .getHibernateLazyInitializer();
                    if (li.getSession() != this ) {
                        throw new TransientObjectException(
                                "The proxy was not associated with this session");
                    }
                    return li.getIdentifier();
                } else {
                    EntityEntry entry = persistenceContext.getEntry(object);
                    if (entry == null) {
                        throw new TransientObjectException(
                                "The instance was not associated with this session");
                    }
                    return entry.getId();
                }
            }

            /**
             * Get the id value for an object that is actually associated with the session. This
             * is a bit stricter than getEntityIdentifierIfNotUnsaved().
             */
            public Serializable getContextEntityIdentifier(Object object) {
                errorIfClosed();
                if (object instanceof  HibernateProxy) {
                    return getProxyIdentifier(object);
                } else {
                    EntityEntry entry = persistenceContext.getEntry(object);
                    return entry != null ? entry.getId() : null;
                }
            }

            private Serializable getProxyIdentifier(Object proxy) {
                return ((HibernateProxy) proxy).getHibernateLazyInitializer()
                        .getIdentifier();
            }

            public Collection filter(Object collection, String filter)
                    throws HibernateException {
                return listFilter(collection, filter, new QueryParameters(
                        new Type[1], new Object[1]));
            }

            public Collection filter(Object collection, String filter,
                    Object value, Type type) throws HibernateException {
                return listFilter(collection, filter,
                        new QueryParameters(new Type[] { null, type },
                                new Object[] { null, value }));
            }

            public Collection filter(Object collection, String filter,
                    Object[] values, Type[] types) throws HibernateException {
                Object[] vals = new Object[values.length + 1];
                Type[] typs = new Type[types.length + 1];
                System.arraycopy(values, 0, vals, 1, values.length);
                System.arraycopy(types, 0, typs, 1, types.length);
                return listFilter(collection, filter, new QueryParameters(typs,
                        vals));
            }

            private FilterQueryPlan getFilterQueryPlan(Object collection,
                    String filter, QueryParameters parameters, boolean shallow)
                    throws HibernateException {
                if (collection == null) {
                    throw new NullPointerException(
                            "null collection passed to filter");
                }

                CollectionEntry entry = persistenceContext
                        .getCollectionEntryOrNull(collection);
                final CollectionPersister roleBeforeFlush = (entry == null) ? null
                        : entry.getLoadedPersister();

                FilterQueryPlan plan = null;
                if (roleBeforeFlush == null) {
                    // if it was previously unreferenced, we need to flush in order to
                    // get its state into the database in order to execute query
                    flush();
                    entry = persistenceContext
                            .getCollectionEntryOrNull(collection);
                    CollectionPersister roleAfterFlush = (entry == null) ? null
                            : entry.getLoadedPersister();
                    if (roleAfterFlush == null) {
                        throw new QueryException(
                                "The collection was unreferenced");
                    }
                    plan = factory.getQueryPlanCache().getFilterQueryPlan(
                            filter, roleAfterFlush.getRole(), shallow,
                            getEnabledFilters());
                } else {
                    // otherwise, we only need to flush if there are in-memory changes
                    // to the queried tables
                    plan = factory.getQueryPlanCache().getFilterQueryPlan(
                            filter, roleBeforeFlush.getRole(), shallow,
                            getEnabledFilters());
                    if (autoFlushIfRequired(plan.getQuerySpaces())) {
                        // might need to run a different filter entirely after the flush
                        // because the collection role may have changed
                        entry = persistenceContext
                                .getCollectionEntryOrNull(collection);
                        CollectionPersister roleAfterFlush = (entry == null) ? null
                                : entry.getLoadedPersister();
                        if (roleBeforeFlush != roleAfterFlush) {
                            if (roleAfterFlush == null) {
                                throw new QueryException(
                                        "The collection was dereferenced");
                            }
                            plan = factory.getQueryPlanCache()
                                    .getFilterQueryPlan(filter,
                                            roleAfterFlush.getRole(), shallow,
                                            getEnabledFilters());
                        }
                    }
                }

                if (parameters != null) {
                    parameters.getPositionalParameterValues()[0] = entry
                            .getLoadedKey();
                    parameters.getPositionalParameterTypes()[0] = entry
                            .getLoadedPersister().getKeyType();
                }

                return plan;
            }

            public List listFilter(Object collection, String filter,
                    QueryParameters queryParameters) throws HibernateException {
                errorIfClosed();
                checkTransactionSynchStatus();
                FilterQueryPlan plan = getFilterQueryPlan(collection, filter,
                        queryParameters, false);
                List results = CollectionHelper.EMPTY_LIST;

                boolean success = false;
                dontFlushFromFind++; //stops flush being called multiple times if this method is recursively called
                try {
                    results = plan.performList(queryParameters, this );
                    success = true;
                } finally {
                    dontFlushFromFind--;
                    afterOperation(success);
                }
                return results;
            }

            public Iterator iterateFilter(Object collection, String filter,
                    QueryParameters queryParameters) throws HibernateException {
                errorIfClosed();
                checkTransactionSynchStatus();
                FilterQueryPlan plan = getFilterQueryPlan(collection, filter,
                        queryParameters, true);
                return plan.performIterate(queryParameters, this );
            }

            public Criteria createCriteria(Class persistentClass, String alias) {
                errorIfClosed();
                checkTransactionSynchStatus();
                return new CriteriaImpl(persistentClass.getName(), alias, this );
            }

            public Criteria createCriteria(String entityName, String alias) {
                errorIfClosed();
                checkTransactionSynchStatus();
                return new CriteriaImpl(entityName, alias, this );
            }

            public Criteria createCriteria(Class persistentClass) {
                errorIfClosed();
                checkTransactionSynchStatus();
                return new CriteriaImpl(persistentClass.getName(), this );
            }

            public Criteria createCriteria(String entityName) {
                errorIfClosed();
                checkTransactionSynchStatus();
                return new CriteriaImpl(entityName, this );
            }

            public ScrollableResults scroll(CriteriaImpl criteria,
                    ScrollMode scrollMode) {
                errorIfClosed();
                checkTransactionSynchStatus();
                String entityName = criteria.getEntityOrClassName();
                CriteriaLoader loader = new CriteriaLoader(
                        getOuterJoinLoadable(entityName), factory, criteria,
                        entityName, getLoadQueryInfluencers());
                autoFlushIfRequired(loader.getQuerySpaces());
                dontFlushFromFind++;
                try {
                    return loader.scroll(this , scrollMode);
                } finally {
                    dontFlushFromFind--;
                }
            }

            public List list(CriteriaImpl criteria) throws HibernateException {
                errorIfClosed();
                checkTransactionSynchStatus();
                String[] implementors = factory.getImplementors(criteria
                        .getEntityOrClassName());
                int size = implementors.length;

                CriteriaLoader[] loaders = new CriteriaLoader[size];
                Set spaces = new HashSet();
                for (int i = 0; i < size; i++) {

                    loaders[i] = new CriteriaLoader(
                            getOuterJoinLoadable(implementors[i]), factory,
                            criteria, implementors[i],
                            getLoadQueryInfluencers());

                    spaces.addAll(loaders[i].getQuerySpaces());

                }

                autoFlushIfRequired(spaces);

                List results = Collections.EMPTY_LIST;
                dontFlushFromFind++;
                boolean success = false;
                try {
                    for (int i = 0; i < size; i++) {
                        final List currentResults = loaders[i].list(this );
                        currentResults.addAll(results);
                        results = currentResults;
                    }
                    success = true;
                } finally {
                    dontFlushFromFind--;
                    afterOperation(success);
                }

                return results;
            }

            private OuterJoinLoadable getOuterJoinLoadable(String entityName)
                    throws MappingException {
                EntityPersister persister = factory
                        .getEntityPersister(entityName);
                if (!(persister instanceof  OuterJoinLoadable)) {
                    throw new MappingException(
                            "class persister is not OuterJoinLoadable: "
                                    + entityName);
                }
                return (OuterJoinLoadable) persister;
            }

            public boolean contains(Object object) {
                errorIfClosed();
                checkTransactionSynchStatus();
                if (object instanceof  HibernateProxy) {
                    //do not use proxiesByKey, since not all
                    //proxies that point to this session's
                    //instances are in that collection!
                    LazyInitializer li = ((HibernateProxy) object)
                            .getHibernateLazyInitializer();
                    if (li.isUninitialized()) {
                        //if it is an uninitialized proxy, pointing
                        //with this session, then when it is accessed,
                        //the underlying instance will be "contained"
                        return li.getSession() == this ;
                    } else {
                        //if it is initialized, see if the underlying
                        //instance is contained, since we need to 
                        //account for the fact that it might have been
                        //evicted
                        object = li.getImplementation();
                    }
                }
                // A session is considered to contain an entity only if the entity has
                // an entry in the session's persistence context and the entry reports
                // that the entity has not been removed
                EntityEntry entry = persistenceContext.getEntry(object);
                return entry != null && entry.getStatus() != Status.DELETED
                        && entry.getStatus() != Status.GONE;
            }

            public Query createQuery(String queryString) {
                errorIfClosed();
                checkTransactionSynchStatus();
                return super .createQuery(queryString);
            }

            public SQLQuery createSQLQuery(String sql) {
                errorIfClosed();
                checkTransactionSynchStatus();
                return super .createSQLQuery(sql);
            }

            public Query createSQLQuery(String sql, String returnAlias,
                    Class returnClass) {
                errorIfClosed();
                checkTransactionSynchStatus();
                return new SQLQueryImpl(sql, new String[] { returnAlias },
                        new Class[] { returnClass }, this , factory
                                .getQueryPlanCache().getSQLParameterMetadata(
                                        sql));
            }

            public Query createSQLQuery(String sql, String returnAliases[],
                    Class returnClasses[]) {
                errorIfClosed();
                checkTransactionSynchStatus();
                return new SQLQueryImpl(sql, returnAliases, returnClasses,
                        this , factory.getQueryPlanCache()
                                .getSQLParameterMetadata(sql));
            }

            public ScrollableResults scrollCustomQuery(CustomQuery customQuery,
                    QueryParameters queryParameters) throws HibernateException {
                errorIfClosed();
                checkTransactionSynchStatus();

                if (log.isTraceEnabled()) {
                    log.trace("scroll SQL query: " + customQuery.getSQL());
                }

                CustomLoader loader = new CustomLoader(customQuery,
                        getFactory());

                autoFlushIfRequired(loader.getQuerySpaces());

                dontFlushFromFind++; //stops flush being called multiple times if this method is recursively called
                try {
                    return loader.scroll(queryParameters, this );
                } finally {
                    dontFlushFromFind--;
                }
            }

            // basically just an adapted copy of find(CriteriaImpl)
            public List listCustomQuery(CustomQuery customQuery,
                    QueryParameters queryParameters) throws HibernateException {
                errorIfClosed();
                checkTransactionSynchStatus();

                if (log.isTraceEnabled()) {
                    log.trace("SQL query: " + customQuery.getSQL());
                }

                CustomLoader loader = new CustomLoader(customQuery,
                        getFactory());

                autoFlushIfRequired(loader.getQuerySpaces());

                dontFlushFromFind++;
                boolean success = false;
                try {
                    List results = loader.list(this , queryParameters);
                    success = true;
                    return results;
                } finally {
                    dontFlushFromFind--;
                    afterOperation(success);
                }
            }

            public SessionFactory getSessionFactory() {
                checkTransactionSynchStatus();
                return factory;
            }

            public void initializeCollection(PersistentCollection collection,
                    boolean writing) throws HibernateException {
                errorIfClosed();
                checkTransactionSynchStatus();
                InitializeCollectionEventListener[] listener = listeners
                        .getInitializeCollectionEventListeners();
                for (int i = 0; i < listener.length; i++) {
                    listener[i]
                            .onInitializeCollection(new InitializeCollectionEvent(
                                    collection, this ));
                }
            }

            public String bestGuessEntityName(Object object) {
                if (object instanceof  HibernateProxy) {
                    LazyInitializer initializer = ((HibernateProxy) object)
                            .getHibernateLazyInitializer();
                    // it is possible for this method to be called during flush processing,
                    // so make certain that we do not accidently initialize an uninitialized proxy
                    if (initializer.isUninitialized()) {
                        return initializer.getEntityName();
                    }
                    object = initializer.getImplementation();
                }
                EntityEntry entry = persistenceContext.getEntry(object);
                if (entry == null) {
                    return guessEntityName(object);
                } else {
                    return entry.getPersister().getEntityName();
                }
            }

            public String getEntityName(Object object) {
                errorIfClosed();
                checkTransactionSynchStatus();
                if (object instanceof  HibernateProxy) {
                    if (!persistenceContext.containsProxy(object)) {
                        throw new TransientObjectException(
                                "proxy was not associated with the session");
                    }
                    object = ((HibernateProxy) object)
                            .getHibernateLazyInitializer().getImplementation();
                }

                EntityEntry entry = persistenceContext.getEntry(object);
                if (entry == null) {
                    throwTransientObjectException(object);
                }
                return entry.getPersister().getEntityName();
            }

            private void throwTransientObjectException(Object object)
                    throws HibernateException {
                throw new TransientObjectException(
                        "object references an unsaved transient instance - save the transient instance before flushing: "
                                + guessEntityName(object));
            }

            public String guessEntityName(Object object)
                    throws HibernateException {
                errorIfClosed();
                return entityNameResolver.resolveEntityName(object);
            }

            public void cancelQuery() throws HibernateException {
                errorIfClosed();
                getBatcher().cancelLastQuery();
            }

            public Interceptor getInterceptor() {
                checkTransactionSynchStatus();
                return interceptor;
            }

            public int getDontFlushFromFind() {
                return dontFlushFromFind;
            }

            public String toString() {
                StringBuffer buf = new StringBuffer(500).append("SessionImpl(");
                if (!isClosed()) {
                    buf.append(persistenceContext).append(";").append(
                            actionQueue);
                } else {
                    buf.append("<closed>");
                }
                return buf.append(')').toString();
            }

            public EventListeners getListeners() {
                return listeners;
            }

            public ActionQueue getActionQueue() {
                errorIfClosed();
                checkTransactionSynchStatus();
                return actionQueue;
            }

            public PersistenceContext getPersistenceContext() {
                errorIfClosed();
                checkTransactionSynchStatus();
                return persistenceContext;
            }

            public SessionStatistics getStatistics() {
                checkTransactionSynchStatus();
                return new SessionStatisticsImpl(this );
            }

            public boolean isEventSource() {
                checkTransactionSynchStatus();
                return true;
            }

            /**
             * {@inheritDoc}
             */
            public boolean isDefaultReadOnly() {
                return persistenceContext.isDefaultReadOnly();
            }

            /**
             * {@inheritDoc}
             */
            public void setDefaultReadOnly(boolean defaultReadOnly) {
                persistenceContext.setDefaultReadOnly(defaultReadOnly);
            }

            public boolean isReadOnly(Object entityOrProxy) {
                errorIfClosed();
                checkTransactionSynchStatus();
                return persistenceContext.isReadOnly(entityOrProxy);
            }

            public void setReadOnly(Object entity, boolean readOnly) {
                errorIfClosed();
                checkTransactionSynchStatus();
                persistenceContext.setReadOnly(entity, readOnly);
            }

            public void doWork(Work work) throws HibernateException {
                try {
                    work.execute(jdbcContext.getConnectionManager()
                            .getConnection());
                    jdbcContext.getConnectionManager().afterStatement();
                } catch (SQLException e) {
                    throw JDBCExceptionHelper.convert(factory.getSettings()
                            .getSQLExceptionConverter(), e,
                            "error executing work");
                }
            }

            public void afterScrollOperation() {
                // nothing to do in a stateful session
            }

            public JDBCContext getJDBCContext() {
                errorIfClosed();
                checkTransactionSynchStatus();
                return jdbcContext;
            }

            public LoadQueryInfluencers getLoadQueryInfluencers() {
                return loadQueryInfluencers;
            }

            // filter support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

            /**
             * {@inheritDoc}
             */
            public Filter getEnabledFilter(String filterName) {
                checkTransactionSynchStatus();
                return loadQueryInfluencers.getEnabledFilter(filterName);
            }

            /**
             * {@inheritDoc}
             */
            public Filter enableFilter(String filterName) {
                errorIfClosed();
                checkTransactionSynchStatus();
                return loadQueryInfluencers.enableFilter(filterName);
            }

            /**
             * {@inheritDoc}
             */
            public void disableFilter(String filterName) {
                errorIfClosed();
                checkTransactionSynchStatus();
                loadQueryInfluencers.disableFilter(filterName);
            }

            /**
             * {@inheritDoc}
             */
            public Object getFilterParameterValue(String filterParameterName) {
                errorIfClosed();
                checkTransactionSynchStatus();
                return loadQueryInfluencers
                        .getFilterParameterValue(filterParameterName);
            }

            /**
             * {@inheritDoc}
             */
            public Type getFilterParameterType(String filterParameterName) {
                errorIfClosed();
                checkTransactionSynchStatus();
                return loadQueryInfluencers
                        .getFilterParameterType(filterParameterName);
            }

            /**
             * {@inheritDoc}
             */
            public Map getEnabledFilters() {
                errorIfClosed();
                checkTransactionSynchStatus();
                return loadQueryInfluencers.getEnabledFilters();
            }

            // internal fetch profile support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

            /**
             * {@inheritDoc}
             */
            public String getFetchProfile() {
                checkTransactionSynchStatus();
                return loadQueryInfluencers.getInternalFetchProfile();
            }

            /**
             * {@inheritDoc}
             */
            public void setFetchProfile(String fetchProfile) {
                errorIfClosed();
                checkTransactionSynchStatus();
                loadQueryInfluencers.setInternalFetchProfile(fetchProfile);
            }

            // fetch profile support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

            public boolean isFetchProfileEnabled(String name)
                    throws UnknownProfileException {
                return loadQueryInfluencers.isFetchProfileEnabled(name);
            }

            public void enableFetchProfile(String name)
                    throws UnknownProfileException {
                loadQueryInfluencers.enableFetchProfile(name);
            }

            public void disableFetchProfile(String name)
                    throws UnknownProfileException {
                loadQueryInfluencers.disableFetchProfile(name);
            }

            private void checkTransactionSynchStatus() {
                if (jdbcContext != null && !isClosed()) {
                    jdbcContext.registerSynchronizationIfPossible();
                }
            }

            /**
             * Used by JDK serialization...
             *
             * @param ois The input stream from which we are being read...
             * @throws IOException Indicates a general IO stream exception
             * @throws ClassNotFoundException Indicates a class resolution issue
             */
            private void readObject(ObjectInputStream ois) throws IOException,
                    ClassNotFoundException {
                log.trace("deserializing session");

                ois.defaultReadObject();

                entityNameResolver = new CoordinatingEntityNameResolver();

                boolean isRootSession = ois.readBoolean();
                connectionReleaseMode = ConnectionReleaseMode
                        .parse((String) ois.readObject());
                entityMode = EntityMode.parse((String) ois.readObject());
                autoClear = ois.readBoolean();
                flushMode = FlushMode.parse((String) ois.readObject());
                cacheMode = CacheMode.parse((String) ois.readObject());
                flushBeforeCompletionEnabled = ois.readBoolean();
                autoCloseSessionEnabled = ois.readBoolean();
                interceptor = (Interceptor) ois.readObject();

                factory = SessionFactoryImpl.deserialize(ois);
                listeners = factory.getEventListeners();

                if (isRootSession) {
                    jdbcContext = JDBCContext.deserialize(ois, this ,
                            interceptor);
                }

                persistenceContext = StatefulPersistenceContext.deserialize(
                        ois, this );
                actionQueue = ActionQueue.deserialize(ois, this );

                loadQueryInfluencers = (LoadQueryInfluencers) ois.readObject();

                childSessionsByEntityMode = (Map) ois.readObject();

                Iterator iter = loadQueryInfluencers.getEnabledFilters()
                        .values().iterator();
                while (iter.hasNext()) {
                    ((FilterImpl) iter.next()).afterDeserialize(factory);
                }

                if (isRootSession && childSessionsByEntityMode != null) {
                    iter = childSessionsByEntityMode.values().iterator();
                    while (iter.hasNext()) {
                        final SessionImpl child = ((SessionImpl) iter.next());
                        child.rootSession = this ;
                        child.jdbcContext = this .jdbcContext;
                    }
                }
            }

            /**
             * Used by JDK serialization...
             *
             * @param oos The output stream to which we are being written...
             * @throws IOException Indicates a general IO stream exception
             */
            private void writeObject(ObjectOutputStream oos) throws IOException {
                if (!jdbcContext.getConnectionManager()
                        .isReadyForSerialization()) {
                    throw new IllegalStateException(
                            "Cannot serialize a session while connected");
                }

                log.trace("serializing session");

                oos.defaultWriteObject();

                oos.writeBoolean(rootSession == null);
                oos.writeObject(connectionReleaseMode.toString());
                oos.writeObject(entityMode.toString());
                oos.writeBoolean(autoClear);
                oos.writeObject(flushMode.toString());
                oos.writeObject(cacheMode.toString());
                oos.writeBoolean(flushBeforeCompletionEnabled);
                oos.writeBoolean(autoCloseSessionEnabled);
                // we need to writeObject() on this since interceptor is user defined
                oos.writeObject(interceptor);

                factory.serialize(oos);

                if (rootSession == null) {
                    jdbcContext.serialize(oos);
                }

                persistenceContext.serialize(oos);
                actionQueue.serialize(oos);

                // todo : look at optimizing these...
                oos.writeObject(loadQueryInfluencers);
                oos.writeObject(childSessionsByEntityMode);
            }

            public Object execute(Callback callback) {
                Connection connection = jdbcContext.getConnectionManager()
                        .getConnection();
                try {
                    return callback.executeOnConnection(connection);
                } catch (SQLException e) {
                    throw JDBCExceptionHelper
                            .convert(getFactory().getSQLExceptionConverter(),
                                    e, "Error creating contextual LOB : "
                                            + e.getMessage());
                } finally {
                    jdbcContext.getConnectionManager().afterStatement();
                }
            }

            private class CoordinatingEntityNameResolver implements 
                    EntityNameResolver {
                public String resolveEntityName(Object entity) {
                    String entityName = interceptor.getEntityName(entity);
                    if (entityName != null) {
                        return entityName;
                    }

                    Iterator itr = factory
                            .iterateEntityNameResolvers(entityMode);
                    while (itr.hasNext()) {
                        final EntityNameResolver resolver = (EntityNameResolver) itr
                                .next();
                        entityName = resolver.resolveEntityName(entity);
                        if (entityName != null) {
                            break;
                        }
                    }
                    if (entityName != null) {
                        return entityName;
                    }

                    // the old-time stand-by...
                    return entity.getClass().getName();
                }
            }

            private class LockRequestImpl implements  LockRequest {
                private final LockOptions lockOptions;

                private LockRequestImpl(LockOptions lo) {
                    lockOptions = new LockOptions();
                    LockOptions.copy(lo, lockOptions);
                }

                public LockMode getLockMode() {
                    return lockOptions.getLockMode();
                }

                public LockRequest setLockMode(LockMode lockMode) {
                    lockOptions.setLockMode(lockMode);
                    return this ;
                }

                public int getTimeOut() {
                    return lockOptions.getTimeOut();
                }

                public LockRequest setTimeOut(int timeout) {
                    lockOptions.setTimeOut(timeout);
                    return this ;
                }

                public boolean getScope() {
                    return lockOptions.getScope();
                }

                public LockRequest setScope(boolean scope) {
                    lockOptions.setScope(scope);
                    return this ;
                }

                public void lock(String entityName, Object object)
                        throws HibernateException {
                    fireLock(entityName, object, lockOptions);
                }

                public void lock(Object object) throws HibernateException {
                    fireLock(object, lockOptions);
                }
            }
        }
w___ww_.___j__av__a_2s__.c___o__m | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.