Save This Page
Home » hibernate-distribution-3.3.1.GA-dist » org.hibernate » impl » [javadoc | source]
    1   /*
    2    * Hibernate, Relational Persistence for Idiomatic Java
    3    *
    4    * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
    5    * indicated by the @author tags or express copyright attribution
    6    * statements applied by the authors.  All third-party contributions are
    7    * distributed under license by Red Hat Middleware LLC.
    8    *
    9    * This copyrighted material is made available to anyone wishing to use, modify,
   10    * copy, or redistribute it subject to the terms and conditions of the GNU
   11    * Lesser General Public License, as published by the Free Software Foundation.
   12    *
   13    * This program is distributed in the hope that it will be useful,
   14    * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
   15    * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
   16    * for more details.
   17    *
   18    * You should have received a copy of the GNU Lesser General Public License
   19    * along with this distribution; if not, write to:
   20    * Free Software Foundation, Inc.
   21    * 51 Franklin Street, Fifth Floor
   22    * Boston, MA  02110-1301  USA
   23    *
   24    */
   25   package org.hibernate.impl;
   26   
   27   import java.io.IOException;
   28   import java.io.ObjectInputStream;
   29   import java.io.ObjectOutputStream;
   30   import java.io.Serializable;
   31   import java.sql.Connection;
   32   import java.sql.SQLException;
   33   import java.util.Collection;
   34   import java.util.Collections;
   35   import java.util.HashMap;
   36   import java.util.HashSet;
   37   import java.util.Iterator;
   38   import java.util.List;
   39   import java.util.Map;
   40   import java.util.Set;
   41   
   42   import org.dom4j.Element;
   43   import org.slf4j.Logger;
   44   import org.slf4j.LoggerFactory;
   45   
   46   import org.hibernate.CacheMode;
   47   import org.hibernate.ConnectionReleaseMode;
   48   import org.hibernate.Criteria;
   49   import org.hibernate.EntityMode;
   50   import org.hibernate.Filter;
   51   import org.hibernate.FlushMode;
   52   import org.hibernate.HibernateException;
   53   import org.hibernate.Interceptor;
   54   import org.hibernate.LockMode;
   55   import org.hibernate.MappingException;
   56   import org.hibernate.ObjectDeletedException;
   57   import org.hibernate.Query;
   58   import org.hibernate.QueryException;
   59   import org.hibernate.ReplicationMode;
   60   import org.hibernate.SQLQuery;
   61   import org.hibernate.ScrollMode;
   62   import org.hibernate.ScrollableResults;
   63   import org.hibernate.Session;
   64   import org.hibernate.SessionException;
   65   import org.hibernate.SessionFactory;
   66   import org.hibernate.Transaction;
   67   import org.hibernate.TransientObjectException;
   68   import org.hibernate.UnresolvableObjectException;
   69   import org.hibernate.collection.PersistentCollection;
   70   import org.hibernate.engine.ActionQueue;
   71   import org.hibernate.engine.CollectionEntry;
   72   import org.hibernate.engine.EntityEntry;
   73   import org.hibernate.engine.EntityKey;
   74   import org.hibernate.engine.FilterDefinition;
   75   import org.hibernate.engine.PersistenceContext;
   76   import org.hibernate.engine.QueryParameters;
   77   import org.hibernate.engine.StatefulPersistenceContext;
   78   import org.hibernate.engine.Status;
   79   import org.hibernate.engine.query.FilterQueryPlan;
   80   import org.hibernate.engine.query.HQLQueryPlan;
   81   import org.hibernate.engine.query.NativeSQLQueryPlan;
   82   import org.hibernate.engine.query.sql.NativeSQLQuerySpecification;
   83   import org.hibernate.event.AutoFlushEvent;
   84   import org.hibernate.event.AutoFlushEventListener;
   85   import org.hibernate.event.DeleteEvent;
   86   import org.hibernate.event.DeleteEventListener;
   87   import org.hibernate.event.DirtyCheckEvent;
   88   import org.hibernate.event.DirtyCheckEventListener;
   89   import org.hibernate.event.EventListeners;
   90   import org.hibernate.event.EventSource;
   91   import org.hibernate.event.EvictEvent;
   92   import org.hibernate.event.EvictEventListener;
   93   import org.hibernate.event.FlushEvent;
   94   import org.hibernate.event.FlushEventListener;
   95   import org.hibernate.event.InitializeCollectionEvent;
   96   import org.hibernate.event.InitializeCollectionEventListener;
   97   import org.hibernate.event.LoadEvent;
   98   import org.hibernate.event.LoadEventListener;
   99   import org.hibernate.event.LoadEventListener.LoadType;
  100   import org.hibernate.event.LockEvent;
  101   import org.hibernate.event.LockEventListener;
  102   import org.hibernate.event.MergeEvent;
  103   import org.hibernate.event.MergeEventListener;
  104   import org.hibernate.event.PersistEvent;
  105   import org.hibernate.event.PersistEventListener;
  106   import org.hibernate.event.RefreshEvent;
  107   import org.hibernate.event.RefreshEventListener;
  108   import org.hibernate.event.ReplicateEvent;
  109   import org.hibernate.event.ReplicateEventListener;
  110   import org.hibernate.event.SaveOrUpdateEvent;
  111   import org.hibernate.event.SaveOrUpdateEventListener;
  112   import org.hibernate.exception.JDBCExceptionHelper;
  113   import org.hibernate.jdbc.Batcher;
  114   import org.hibernate.jdbc.JDBCContext;
  115   import org.hibernate.jdbc.Work;
  116   import org.hibernate.loader.criteria.CriteriaLoader;
  117   import org.hibernate.loader.custom.CustomLoader;
  118   import org.hibernate.loader.custom.CustomQuery;
  119   import org.hibernate.persister.collection.CollectionPersister;
  120   import org.hibernate.persister.entity.EntityPersister;
  121   import org.hibernate.persister.entity.OuterJoinLoadable;
  122   import org.hibernate.pretty.MessageHelper;
  123   import org.hibernate.proxy.HibernateProxy;
  124   import org.hibernate.proxy.LazyInitializer;
  125   import org.hibernate.stat.SessionStatistics;
  126   import org.hibernate.stat.SessionStatisticsImpl;
  127   import org.hibernate.tuple.DynamicMapInstantiator;
  128   import org.hibernate.type.Type;
  129   import org.hibernate.util.ArrayHelper;
  130   import org.hibernate.util.CollectionHelper;
  131   import org.hibernate.util.StringHelper;
  132   
  133   
  134   /**
  135    * Concrete implementation of a Session, and also the central, organizing component
  136    * of Hibernate's internal implementation. As such, this class exposes two interfaces;
  137    * Session itself, to the application, and SessionImplementor, to other components
  138    * of Hibernate. This class is not threadsafe.
  139    *
  140    * @author Gavin King
  141    */
  142   public final class SessionImpl extends AbstractSessionImpl 
  143   		implements EventSource, org.hibernate.classic.Session, JDBCContext.Context {
  144   
  145   	// todo : need to find a clean way to handle the "event source" role
  146   	// a seperate classs responsible for generating/dispatching events just duplicates most of the Session methods...
  147   	// passing around seperate reto interceptor, factory, actionQueue, and persistentContext is not manageable...
  148   
  149   	private static final Logger log = LoggerFactory.getLogger(SessionImpl.class);
  150   
  151   	private transient EntityMode entityMode = EntityMode.POJO;
  152   	private transient boolean autoClear; //for EJB3
  153   	
  154   	private transient long timestamp;
  155   	private transient FlushMode flushMode = FlushMode.AUTO;
  156   	private transient CacheMode cacheMode = CacheMode.NORMAL;
  157   
  158   	private transient Interceptor interceptor;
  159   
  160   	private transient int dontFlushFromFind = 0;
  161   
  162   	private transient ActionQueue actionQueue;
  163   	private transient StatefulPersistenceContext persistenceContext;
  164   	private transient JDBCContext jdbcContext;
  165   	private transient EventListeners listeners;
  166   
  167   	private transient boolean flushBeforeCompletionEnabled;
  168   	private transient boolean autoCloseSessionEnabled;
  169   	private transient ConnectionReleaseMode connectionReleaseMode;
  170   	
  171   	private transient String fetchProfile;
  172   
  173   	private transient Map enabledFilters = new HashMap();
  174   
  175   	private transient Session rootSession;
  176   	private transient Map childSessionsByEntityMode;
  177   
  178   	/**
  179   	 * Constructor used in building "child sessions".
  180   	 *
  181   	 * @param parent The parent session
  182   	 * @param entityMode
  183   	 */
  184   	private SessionImpl(SessionImpl parent, EntityMode entityMode) {
  185   		super( parent.factory );
  186   		this.rootSession = parent;
  187   		this.timestamp = parent.timestamp;
  188   		this.jdbcContext = parent.jdbcContext;
  189   		this.interceptor = parent.interceptor;
  190   		this.listeners = parent.listeners;
  191   		this.actionQueue = new ActionQueue( this );
  192   		this.entityMode = entityMode;
  193   		this.persistenceContext = new StatefulPersistenceContext( this );
  194   		this.flushBeforeCompletionEnabled = false;
  195   		this.autoCloseSessionEnabled = false;
  196   		this.connectionReleaseMode = null;
  197   
  198   		if ( factory.getStatistics().isStatisticsEnabled() ) {
  199   			factory.getStatisticsImplementor().openSession();
  200   		}
  201   
  202   		log.debug( "opened session [" + entityMode + "]" );
  203   	}
  204   
  205   	/**
  206   	 * Constructor used for openSession(...) processing, as well as construction
  207   	 * of sessions for getCurrentSession().
  208   	 *
  209   	 * @param connection The user-supplied connection to use for this session.
  210   	 * @param factory The factory from which this session was obtained
  211   	 * @param autoclose NOT USED
  212   	 * @param timestamp The timestamp for this session
  213   	 * @param interceptor The interceptor to be applied to this session
  214   	 * @param entityMode The entity-mode for this session
  215   	 * @param flushBeforeCompletionEnabled Should we auto flush before completion of transaction
  216   	 * @param autoCloseSessionEnabled Should we auto close after completion of transaction
  217   	 * @param connectionReleaseMode The mode by which we should release JDBC connections.
  218   	 */
  219   	SessionImpl(
  220   			final Connection connection,
  221   			final SessionFactoryImpl factory,
  222   			final boolean autoclose,
  223   			final long timestamp,
  224   			final Interceptor interceptor,
  225   			final EntityMode entityMode,
  226   			final boolean flushBeforeCompletionEnabled,
  227   			final boolean autoCloseSessionEnabled,
  228   			final ConnectionReleaseMode connectionReleaseMode) {
  229   		super( factory );
  230   		this.rootSession = null;
  231   		this.timestamp = timestamp;
  232   		this.entityMode = entityMode;
  233   		this.interceptor = interceptor;
  234   		this.listeners = factory.getEventListeners();
  235   		this.actionQueue = new ActionQueue( this );
  236   		this.persistenceContext = new StatefulPersistenceContext( this );
  237   		this.flushBeforeCompletionEnabled = flushBeforeCompletionEnabled;
  238   		this.autoCloseSessionEnabled = autoCloseSessionEnabled;
  239   		this.connectionReleaseMode = connectionReleaseMode;
  240   		this.jdbcContext = new JDBCContext( this, connection, interceptor );
  241   
  242   		if ( factory.getStatistics().isStatisticsEnabled() ) {
  243   			factory.getStatisticsImplementor().openSession();
  244   		}
  245   
  246   		if ( log.isDebugEnabled() ) {
  247   			log.debug( "opened session at timestamp: " + timestamp );
  248   		}
  249   	}
  250   
  251   	public Session getSession(EntityMode entityMode) {
  252   		if ( this.entityMode == entityMode ) {
  253   			return this;
  254   		}
  255   
  256   		if ( rootSession != null ) {
  257   			rootSession.getSession( entityMode );
  258   		}
  259   
  260   		errorIfClosed();
  261   		checkTransactionSynchStatus();
  262   
  263   		SessionImpl rtn = null;
  264   		if ( childSessionsByEntityMode == null ) {
  265   			childSessionsByEntityMode = new HashMap();
  266   		}
  267   		else {
  268   			rtn = (SessionImpl) childSessionsByEntityMode.get( entityMode );
  269   		}
  270   
  271   		if ( rtn == null ) {
  272   			rtn = new SessionImpl( this, entityMode );
  273   			childSessionsByEntityMode.put( entityMode, rtn );
  274   		}
  275   
  276   		return rtn;
  277   	}
  278   
  279   	public void clear() {
  280   		errorIfClosed();
  281   		checkTransactionSynchStatus();
  282   		persistenceContext.clear();
  283   		actionQueue.clear();
  284   	}
  285   
  286   	public Batcher getBatcher() {
  287   		errorIfClosed();
  288   		checkTransactionSynchStatus();
  289   		// TODO : should remove this exposure
  290   		//  and have all references to the session's batcher use the ConnectionManager.
  291   		return jdbcContext.getConnectionManager().getBatcher();
  292   	}
  293   
  294   	public long getTimestamp() {
  295   		checkTransactionSynchStatus();
  296   		return timestamp;
  297   	}
  298   
  299   	public Connection close() throws HibernateException {
  300   		log.trace( "closing session" );
  301   		if ( isClosed() ) {
  302   			throw new SessionException( "Session was already closed" );
  303   		}
  304   		
  305   
  306   		if ( factory.getStatistics().isStatisticsEnabled() ) {
  307   			factory.getStatisticsImplementor().closeSession();
  308   		}
  309   
  310   		try {
  311   			try {
  312   				if ( childSessionsByEntityMode != null ) {
  313   					Iterator childSessions = childSessionsByEntityMode.values().iterator();
  314   					while ( childSessions.hasNext() ) {
  315   						final SessionImpl child = ( SessionImpl ) childSessions.next();
  316   						child.close();
  317   					}
  318   				}
  319   			}
  320   			catch( Throwable t ) {
  321   				// just ignore
  322   			}
  323   
  324   			if ( rootSession == null ) {
  325   				return jdbcContext.getConnectionManager().close();
  326   			}
  327   			else {
  328   				return null;
  329   			}
  330   		}
  331   		finally {
  332   			setClosed();
  333   			cleanup();
  334   		}
  335   	}
  336   
  337   	public ConnectionReleaseMode getConnectionReleaseMode() {
  338   		checkTransactionSynchStatus();
  339   		return connectionReleaseMode;
  340   	}
  341   
  342   	public boolean isAutoCloseSessionEnabled() {
  343   		return autoCloseSessionEnabled;
  344   	}
  345   
  346   	public boolean isOpen() {
  347   		checkTransactionSynchStatus();
  348   		return !isClosed();
  349   	}
  350   
  351   	public boolean isFlushModeNever() {
  352   		return FlushMode.isManualFlushMode( getFlushMode() );
  353   	}
  354   
  355   	public boolean isFlushBeforeCompletionEnabled() {
  356   		return flushBeforeCompletionEnabled;
  357   	}
  358   
  359   	public void managedFlush() {
  360   		if ( isClosed() ) {
  361   			log.trace( "skipping auto-flush due to session closed" );
  362   			return;
  363   		}
  364   		log.trace("automatically flushing session");
  365   		flush();
  366   		
  367   		if ( childSessionsByEntityMode != null ) {
  368   			Iterator iter = childSessionsByEntityMode.values().iterator();
  369   			while ( iter.hasNext() ) {
  370   				( (Session) iter.next() ).flush();
  371   			}
  372   		}
  373   	}
  374   
  375   	public boolean shouldAutoClose() {
  376   		return isAutoCloseSessionEnabled() && !isClosed();
  377   	}
  378   
  379   	public void managedClose() {
  380   		log.trace( "automatically closing session" );
  381   		close();
  382   	}
  383   
  384   	public Connection connection() throws HibernateException {
  385   		errorIfClosed();
  386   		return jdbcContext.borrowConnection();
  387   	}
  388   
  389   	public boolean isConnected() {
  390   		checkTransactionSynchStatus();
  391   		return !isClosed() && jdbcContext.getConnectionManager().isCurrentlyConnected();
  392   	}
  393   	
  394   	public boolean isTransactionInProgress() {
  395   		checkTransactionSynchStatus();
  396   		return !isClosed() && jdbcContext.isTransactionInProgress();
  397   	}
  398   
  399   	public Connection disconnect() throws HibernateException {
  400   		errorIfClosed();
  401   		log.debug( "disconnecting session" );
  402   		return jdbcContext.getConnectionManager().manualDisconnect();
  403   	}
  404   
  405   	public void reconnect() throws HibernateException {
  406   		errorIfClosed();
  407   		log.debug( "reconnecting session" );
  408   		checkTransactionSynchStatus();
  409   		jdbcContext.getConnectionManager().manualReconnect();
  410   	}
  411   
  412   	public void reconnect(Connection conn) throws HibernateException {
  413   		errorIfClosed();
  414   		log.debug( "reconnecting session" );
  415   		checkTransactionSynchStatus();
  416   		jdbcContext.getConnectionManager().manualReconnect( conn );
  417   	}
  418   
  419   	public void beforeTransactionCompletion(Transaction tx) {
  420   		log.trace( "before transaction completion" );
  421   		if ( rootSession == null ) {
  422   			try {
  423   				interceptor.beforeTransactionCompletion(tx);
  424   			}
  425   			catch (Throwable t) {
  426   				log.error("exception in interceptor beforeTransactionCompletion()", t);
  427   			}
  428   		}
  429   	}
  430   	
  431   	public void setAutoClear(boolean enabled) {
  432   		errorIfClosed();
  433   		autoClear = enabled;
  434   	}
  435   	
  436   	/**
  437   	 * Check if there is a Hibernate or JTA transaction in progress and, 
  438   	 * if there is not, flush if necessary, make sure the connection has 
  439   	 * been committed (if it is not in autocommit mode) and run the after 
  440   	 * completion processing
  441   	 */
  442   	public void afterOperation(boolean success) {
  443   		if ( !jdbcContext.isTransactionInProgress() ) {
  444   			jdbcContext.afterNontransactionalQuery( success );
  445   		}
  446   	}
  447   
  448   	public void afterTransactionCompletion(boolean success, Transaction tx) {
  449   		log.trace( "after transaction completion" );
  450   		persistenceContext.afterTransactionCompletion();
  451   		actionQueue.afterTransactionCompletion(success);
  452   		if ( rootSession == null && tx != null ) {
  453   			try {
  454   				interceptor.afterTransactionCompletion(tx);
  455   			}
  456   			catch (Throwable t) {
  457   				log.error("exception in interceptor afterTransactionCompletion()", t);
  458   			}
  459   		}
  460   		if ( autoClear ) {
  461   			clear();
  462   		}
  463   	}
  464   
  465   	/**
  466   	 * clear all the internal collections, just 
  467   	 * to help the garbage collector, does not
  468   	 * clear anything that is needed during the
  469   	 * afterTransactionCompletion() phase
  470   	 */
  471   	private void cleanup() {
  472   		persistenceContext.clear();
  473   	}
  474   
  475   	public LockMode getCurrentLockMode(Object object) throws HibernateException {
  476   		errorIfClosed();
  477   		checkTransactionSynchStatus();
  478   		if ( object == null ) {
  479   			throw new NullPointerException( "null object passed to getCurrentLockMode()" );
  480   		}
  481   		if ( object instanceof HibernateProxy ) {
  482   			object = ( (HibernateProxy) object ).getHibernateLazyInitializer().getImplementation(this);
  483   			if ( object == null ) {
  484   				return LockMode.NONE;
  485   			}
  486   		}
  487   		EntityEntry e = persistenceContext.getEntry(object);
  488   		if ( e == null ) {
  489   			throw new TransientObjectException( "Given object not associated with the session" );
  490   		}
  491   		if ( e.getStatus() != Status.MANAGED ) {
  492   			throw new ObjectDeletedException( 
  493   					"The given object was deleted", 
  494   					e.getId(), 
  495   					e.getPersister().getEntityName() 
  496   				);
  497   		}
  498   		return e.getLockMode();
  499   	}
  500   
  501   	public Object getEntityUsingInterceptor(EntityKey key) throws HibernateException {
  502   		errorIfClosed();
  503   		// todo : should this get moved to PersistentContext?
  504   		// logically, is PersistentContext the "thing" to which an interceptor gets attached?
  505   		final Object result = persistenceContext.getEntity(key);
  506   		if ( result == null ) {
  507   			final Object newObject = interceptor.getEntity( key.getEntityName(), key.getIdentifier() );
  508   			if ( newObject != null ) {
  509   				lock( newObject, LockMode.NONE );
  510   			}
  511   			return newObject;
  512   		}
  513   		else {
  514   			return result;
  515   		}
  516   	}
  517   
  518   
  519   	// saveOrUpdate() operations ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  520   
  521   	public void saveOrUpdate(Object object) throws HibernateException {
  522   		saveOrUpdate(null, object);
  523   	}
  524   
  525   	public void saveOrUpdate(String entityName, Object obj) throws HibernateException {
  526   		fireSaveOrUpdate( new SaveOrUpdateEvent(entityName, obj, this) );
  527   	}
  528   
  529   	private void fireSaveOrUpdate(SaveOrUpdateEvent event) {
  530   		errorIfClosed();
  531   		checkTransactionSynchStatus();
  532   		SaveOrUpdateEventListener[] saveOrUpdateEventListener = listeners.getSaveOrUpdateEventListeners();
  533   		for ( int i = 0; i < saveOrUpdateEventListener.length; i++ ) {
  534   			saveOrUpdateEventListener[i].onSaveOrUpdate(event);
  535   		}
  536   	}
  537   
  538   
  539   	// save() operations ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  540   
  541   	public void save(Object obj, Serializable id) throws HibernateException {
  542   		save(null, obj, id);
  543   	}
  544   
  545   	public Serializable save(Object obj) throws HibernateException {
  546   		return save(null, obj);
  547   	}
  548   
  549   	public Serializable save(String entityName, Object object) throws HibernateException {
  550   		return fireSave( new SaveOrUpdateEvent(entityName, object, this) );
  551   	}
  552   
  553   	public void save(String entityName, Object object, Serializable id) throws HibernateException {
  554   		fireSave( new SaveOrUpdateEvent(entityName, object, id, this) );
  555   	}
  556   
  557   	private Serializable fireSave(SaveOrUpdateEvent event) {
  558   		errorIfClosed();
  559   		checkTransactionSynchStatus();
  560   		SaveOrUpdateEventListener[] saveEventListener = listeners.getSaveEventListeners();
  561   		for ( int i = 0; i < saveEventListener.length; i++ ) {
  562   			saveEventListener[i].onSaveOrUpdate(event);
  563   		}
  564   		return event.getResultId();
  565   	}
  566   
  567   
  568   	// update() operations ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  569   
  570   	public void update(Object obj) throws HibernateException {
  571   		update(null, obj);
  572   	}
  573   
  574   	public void update(Object obj, Serializable id) throws HibernateException {
  575   		update(null, obj, id);
  576   	}
  577   
  578   	public void update(String entityName, Object object) throws HibernateException {
  579   		fireUpdate( new SaveOrUpdateEvent(entityName, object, this) );
  580   	}
  581   
  582   	public void update(String entityName, Object object, Serializable id) throws HibernateException {
  583   		fireUpdate(new SaveOrUpdateEvent(entityName, object, id, this));
  584   	}
  585   
  586   	private void fireUpdate(SaveOrUpdateEvent event) {
  587   		errorIfClosed();
  588   		checkTransactionSynchStatus();
  589   		SaveOrUpdateEventListener[] updateEventListener = listeners.getUpdateEventListeners();
  590   		for ( int i = 0; i < updateEventListener.length; i++ ) {
  591   			updateEventListener[i].onSaveOrUpdate(event);
  592   		}
  593   	}
  594   
  595   
  596   	// lock() operations ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  597   
  598   	public void lock(String entityName, Object object, LockMode lockMode) throws HibernateException {
  599   		fireLock( new LockEvent(entityName, object, lockMode, this) );
  600   	}
  601   
  602   	public void lock(Object object, LockMode lockMode) throws HibernateException {
  603   		fireLock( new LockEvent(object, lockMode, this) );
  604   	}
  605   
  606   	private void fireLock(LockEvent lockEvent) {
  607   		errorIfClosed();
  608   		checkTransactionSynchStatus();
  609   		LockEventListener[] lockEventListener = listeners.getLockEventListeners();
  610   		for ( int i = 0; i < lockEventListener.length; i++ ) {
  611   			lockEventListener[i].onLock( lockEvent );
  612   		}
  613   	}
  614   
  615   
  616   	// persist() operations ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  617   
  618   	public void persist(String entityName, Object object) throws HibernateException {
  619   		firePersist( new PersistEvent(entityName, object, this) );
  620   	}
  621   
  622   	public void persist(Object object) throws HibernateException {
  623   		persist(null, object);
  624   	}
  625   
  626   	public void persist(String entityName, Object object, Map copiedAlready)
  627   	throws HibernateException {
  628   		firePersist( copiedAlready, new PersistEvent(entityName, object, this) );
  629   	}
  630   
  631   	private void firePersist(Map copiedAlready, PersistEvent event) {
  632   		errorIfClosed();
  633   		checkTransactionSynchStatus();
  634   		PersistEventListener[] persistEventListener = listeners.getPersistEventListeners();
  635   		for ( int i = 0; i < persistEventListener.length; i++ ) {
  636   			persistEventListener[i].onPersist(event, copiedAlready);
  637   		}
  638   	}
  639   
  640   	private void firePersist(PersistEvent event) {
  641   		errorIfClosed();
  642   		checkTransactionSynchStatus();
  643   		PersistEventListener[] createEventListener = listeners.getPersistEventListeners();
  644   		for ( int i = 0; i < createEventListener.length; i++ ) {
  645   			createEventListener[i].onPersist(event);
  646   		}
  647   	}
  648   
  649   
  650   	// persistOnFlush() operations ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  651   
  652   	public void persistOnFlush(String entityName, Object object)
  653   			throws HibernateException {
  654   		firePersistOnFlush( new PersistEvent(entityName, object, this) );
  655   	}
  656   
  657   	public void persistOnFlush(Object object) throws HibernateException {
  658   		persist(null, object);
  659   	}
  660   
  661   	public void persistOnFlush(String entityName, Object object, Map copiedAlready)
  662   			throws HibernateException {
  663   		firePersistOnFlush( copiedAlready, new PersistEvent(entityName, object, this) );
  664   	}
  665   
  666   	private void firePersistOnFlush(Map copiedAlready, PersistEvent event) {
  667   		errorIfClosed();
  668   		checkTransactionSynchStatus();
  669   		PersistEventListener[] persistEventListener = listeners.getPersistOnFlushEventListeners();
  670   		for ( int i = 0; i < persistEventListener.length; i++ ) {
  671   			persistEventListener[i].onPersist(event, copiedAlready);
  672   		}
  673   	}
  674   
  675   	private void firePersistOnFlush(PersistEvent event) {
  676   		errorIfClosed();
  677   		checkTransactionSynchStatus();
  678   		PersistEventListener[] createEventListener = listeners.getPersistOnFlushEventListeners();
  679   		for ( int i = 0; i < createEventListener.length; i++ ) {
  680   			createEventListener[i].onPersist(event);
  681   		}
  682   	}
  683   
  684   
  685   	// merge() operations ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  686   
  687   	public Object merge(String entityName, Object object) throws HibernateException {
  688   		return fireMerge( new MergeEvent(entityName, object, this) );
  689   	}
  690   
  691   	public Object merge(Object object) throws HibernateException {
  692   		return merge(null, object);
  693   	}
  694   
  695   	public void merge(String entityName, Object object, Map copiedAlready) throws HibernateException {
  696   		fireMerge( copiedAlready, new MergeEvent(entityName, object, this) );
  697   	}
  698   
  699   	private Object fireMerge(MergeEvent event) {
  700   		errorIfClosed();
  701   		checkTransactionSynchStatus();
  702   		MergeEventListener[] mergeEventListener = listeners.getMergeEventListeners();
  703   		for ( int i = 0; i < mergeEventListener.length; i++ ) {
  704   			mergeEventListener[i].onMerge(event);
  705   		}
  706   		return event.getResult();
  707   	}
  708   
  709   	private void fireMerge(Map copiedAlready, MergeEvent event) {
  710   		errorIfClosed();
  711   		checkTransactionSynchStatus();
  712   		MergeEventListener[] mergeEventListener = listeners.getMergeEventListeners();
  713   		for ( int i = 0; i < mergeEventListener.length; i++ ) {
  714   			mergeEventListener[i].onMerge(event, copiedAlready);
  715   		}
  716   	}
  717   
  718   
  719   	// saveOrUpdateCopy() operations ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  720   
  721   	public Object saveOrUpdateCopy(String entityName, Object object)
  722   			throws HibernateException {
  723   		return fireSaveOrUpdateCopy( new MergeEvent(entityName, object, this) );
  724   	}
  725   
  726   	public Object saveOrUpdateCopy(Object object) throws HibernateException {
  727   		return saveOrUpdateCopy( null, object );
  728   	}
  729   
  730   	public Object saveOrUpdateCopy(String entityName, Object object, Serializable id)
  731   			throws HibernateException {
  732   		return fireSaveOrUpdateCopy( new MergeEvent(entityName, object, id, this) );
  733   	}
  734   
  735   	public Object saveOrUpdateCopy(Object object, Serializable id)
  736   			throws HibernateException {
  737   		return saveOrUpdateCopy( null, object, id );
  738   	}
  739   
  740   	public void saveOrUpdateCopy(String entityName, Object object, Map copiedAlready)
  741   			throws HibernateException {
  742   		fireSaveOrUpdateCopy( copiedAlready, new MergeEvent( entityName, object, this ) );
  743   	}
  744   
  745   	private void fireSaveOrUpdateCopy(Map copiedAlready, MergeEvent event) {
  746   		errorIfClosed();
  747   		checkTransactionSynchStatus();
  748   		MergeEventListener[] saveOrUpdateCopyEventListener = listeners.getSaveOrUpdateCopyEventListeners();
  749   		for ( int i = 0; i < saveOrUpdateCopyEventListener.length; i++ ) {
  750   			saveOrUpdateCopyEventListener[i].onMerge(event, copiedAlready);
  751   		}
  752   	}
  753   
  754   	private Object fireSaveOrUpdateCopy(MergeEvent event) {
  755   		errorIfClosed();
  756   		checkTransactionSynchStatus();
  757   		MergeEventListener[] saveOrUpdateCopyEventListener = listeners.getSaveOrUpdateCopyEventListeners();
  758   		for ( int i = 0; i < saveOrUpdateCopyEventListener.length; i++ ) {
  759   			saveOrUpdateCopyEventListener[i].onMerge(event);
  760   		}
  761   		return event.getResult();
  762   	}
  763   
  764   
  765   	// delete() operations ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  766   
  767   	/**
  768   	 * Delete a persistent object
  769   	 */
  770   	public void delete(Object object) throws HibernateException {
  771   		fireDelete( new DeleteEvent(object, this) );
  772   	}
  773   
  774   	/**
  775   	 * Delete a persistent object (by explicit entity name)
  776   	 */
  777   	public void delete(String entityName, Object object) throws HibernateException {
  778   		fireDelete( new DeleteEvent( entityName, object, this ) );
  779   	}
  780   
  781   	/**
  782   	 * Delete a persistent object
  783   	 */
  784   	public void delete(String entityName, Object object, boolean isCascadeDeleteEnabled, Set transientEntities) throws HibernateException {
  785   		fireDelete( new DeleteEvent( entityName, object, isCascadeDeleteEnabled, this ), transientEntities );
  786   	}
  787   
  788   	private void fireDelete(DeleteEvent event) {
  789   		errorIfClosed();
  790   		checkTransactionSynchStatus();
  791   		DeleteEventListener[] deleteEventListener = listeners.getDeleteEventListeners();
  792   		for ( int i = 0; i < deleteEventListener.length; i++ ) {
  793   			deleteEventListener[i].onDelete( event );
  794   		}
  795   	}
  796   
  797   	private void fireDelete(DeleteEvent event, Set transientEntities) {
  798   		errorIfClosed();
  799   		checkTransactionSynchStatus();
  800   		DeleteEventListener[] deleteEventListener = listeners.getDeleteEventListeners();
  801   		for ( int i = 0; i < deleteEventListener.length; i++ ) {
  802   			deleteEventListener[i].onDelete( event, transientEntities );
  803   		}
  804   	}
  805   
  806   
  807   	// load()/get() operations ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  808   
  809   	public void load(Object object, Serializable id) throws HibernateException {
  810   		LoadEvent event = new LoadEvent(id, object, this);
  811   		fireLoad( event, LoadEventListener.RELOAD );
  812   	}
  813   
  814   	public Object load(Class entityClass, Serializable id) throws HibernateException {
  815   		return load( entityClass.getName(), id );
  816   	}
  817   
  818   	public Object load(String entityName, Serializable id) throws HibernateException {
  819   		LoadEvent event = new LoadEvent(id, entityName, false, this);
  820   		boolean success = false;
  821   		try {
  822   			fireLoad( event, LoadEventListener.LOAD );
  823   			if ( event.getResult() == null ) {
  824   				getFactory().getEntityNotFoundDelegate().handleEntityNotFound( entityName, id );
  825   			}
  826   			success = true;
  827   			return event.getResult();
  828   		}
  829   		finally {
  830   			afterOperation(success);
  831   		}
  832   	}
  833   
  834   	public Object get(Class entityClass, Serializable id) throws HibernateException {
  835   		return get( entityClass.getName(), id );
  836   	}
  837   
  838   	public Object get(String entityName, Serializable id) throws HibernateException {
  839   		LoadEvent event = new LoadEvent(id, entityName, false, this);
  840   		boolean success = false;
  841   		try {
  842   			fireLoad(event, LoadEventListener.GET);
  843   			success = true;
  844   			return event.getResult();
  845   		}
  846   		finally {
  847   			afterOperation(success);
  848   		}
  849   	}
  850   
  851   	/**
  852   	 * Load the data for the object with the specified id into a newly created object.
  853   	 * This is only called when lazily initializing a proxy.
  854   	 * Do NOT return a proxy.
  855   	 */
  856   	public Object immediateLoad(String entityName, Serializable id) throws HibernateException {
  857   		if ( log.isDebugEnabled() ) {
  858   			EntityPersister persister = getFactory().getEntityPersister(entityName);
  859   			log.debug( "initializing proxy: " + MessageHelper.infoString( persister, id, getFactory() ) );
  860   		}
  861   		
  862   		LoadEvent event = new LoadEvent(id, entityName, true, this);
  863   		fireLoad(event, LoadEventListener.IMMEDIATE_LOAD);
  864   		return event.getResult();
  865   	}
  866   
  867   	public Object internalLoad(String entityName, Serializable id, boolean eager, boolean nullable) throws HibernateException {
  868   		// todo : remove
  869   		LoadEventListener.LoadType type = nullable ? 
  870   				LoadEventListener.INTERNAL_LOAD_NULLABLE : 
  871   				eager ? LoadEventListener.INTERNAL_LOAD_EAGER : LoadEventListener.INTERNAL_LOAD_LAZY;
  872   		LoadEvent event = new LoadEvent(id, entityName, true, this);
  873   		fireLoad(event, type);
  874   		if ( !nullable ) {
  875   			UnresolvableObjectException.throwIfNull( event.getResult(), id, entityName );
  876   		}
  877   		return event.getResult();
  878   	}
  879   
  880   	public Object load(Class entityClass, Serializable id, LockMode lockMode) throws HibernateException {
  881   		return load( entityClass.getName(), id, lockMode );
  882   	}
  883   
  884   	public Object load(String entityName, Serializable id, LockMode lockMode) throws HibernateException {
  885   		LoadEvent event = new LoadEvent(id, entityName, lockMode, this);
  886   		fireLoad( event, LoadEventListener.LOAD );
  887   		return event.getResult();
  888   	}
  889   
  890   	public Object get(Class entityClass, Serializable id, LockMode lockMode) throws HibernateException {
  891   		return get( entityClass.getName(), id, lockMode );
  892   	}
  893   
  894   	public Object get(String entityName, Serializable id, LockMode lockMode) throws HibernateException {
  895   		LoadEvent event = new LoadEvent(id, entityName, lockMode, this);
  896   	   	fireLoad(event, LoadEventListener.GET);
  897   		return event.getResult();
  898   	}
  899   
  900   	private void fireLoad(LoadEvent event, LoadType loadType) {
  901   		errorIfClosed();
  902   		checkTransactionSynchStatus();
  903   		LoadEventListener[] loadEventListener = listeners.getLoadEventListeners();
  904   		for ( int i = 0; i < loadEventListener.length; i++ ) {
  905   			loadEventListener[i].onLoad(event, loadType);
  906   		}
  907   	}
  908   
  909   
  910   	// refresh() operations ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  911   
  912   	public void refresh(Object object) throws HibernateException {
  913   		fireRefresh( new RefreshEvent(object, this) );
  914   	}
  915   
  916   	public void refresh(Object object, LockMode lockMode) throws HibernateException {
  917   		fireRefresh( new RefreshEvent(object, lockMode, this) );
  918   	}
  919   
  920   	public void refresh(Object object, Map refreshedAlready) throws HibernateException {
  921   		fireRefresh( refreshedAlready, new RefreshEvent(object, this) );
  922   	}
  923   
  924   	private void fireRefresh(RefreshEvent refreshEvent) {
  925   		errorIfClosed();
  926   		checkTransactionSynchStatus();
  927   		RefreshEventListener[] refreshEventListener = listeners.getRefreshEventListeners();
  928   		for ( int i = 0; i < refreshEventListener.length; i++ ) {
  929   			refreshEventListener[i].onRefresh( refreshEvent );
  930   		}
  931   	}
  932   
  933   	private void fireRefresh(Map refreshedAlready, RefreshEvent refreshEvent) {
  934   		errorIfClosed();
  935   		checkTransactionSynchStatus();
  936   		RefreshEventListener[] refreshEventListener = listeners.getRefreshEventListeners();
  937   		for ( int i = 0; i < refreshEventListener.length; i++ ) {
  938   			refreshEventListener[i].onRefresh( refreshEvent, refreshedAlready );
  939   		}
  940   	}
  941   
  942   
  943   	// replicate() operations ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  944   
  945   	public void replicate(Object obj, ReplicationMode replicationMode) throws HibernateException {
  946   		fireReplicate( new ReplicateEvent(obj, replicationMode, this) );
  947   	}
  948   
  949   	public void replicate(String entityName, Object obj, ReplicationMode replicationMode)
  950   	throws HibernateException {
  951   		fireReplicate( new ReplicateEvent(entityName, obj, replicationMode, this) );
  952   	}
  953   
  954   	private void fireReplicate(ReplicateEvent event) {
  955   		errorIfClosed();
  956   		checkTransactionSynchStatus();
  957   		ReplicateEventListener[] replicateEventListener = listeners.getReplicateEventListeners();
  958   		for ( int i = 0; i < replicateEventListener.length; i++ ) {
  959   			replicateEventListener[i].onReplicate(event);
  960   		}
  961   	}
  962   
  963   
  964   	// evict() operations ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  965   
  966   	/**
  967   	 * remove any hard references to the entity that are held by the infrastructure
  968   	 * (references held by application or other persistant instances are okay)
  969   	 */
  970   	public void evict(Object object) throws HibernateException {
  971   		fireEvict( new EvictEvent(object, this) );
  972   	}
  973   
  974   	private void fireEvict(EvictEvent evictEvent) {
  975   		errorIfClosed();
  976   		checkTransactionSynchStatus();
  977   		EvictEventListener[] evictEventListener = listeners.getEvictEventListeners();
  978   		for ( int i = 0; i < evictEventListener.length; i++ ) {
  979   			evictEventListener[i].onEvict( evictEvent );
  980   		}
  981   	}
  982   
  983   	/**
  984   	 * detect in-memory changes, determine if the changes are to tables
  985   	 * named in the query and, if so, complete execution the flush
  986   	 */
  987   	protected boolean autoFlushIfRequired(Set querySpaces) throws HibernateException {
  988   		errorIfClosed();
  989   		if ( ! isTransactionInProgress() ) {
  990   			// do not auto-flush while outside a transaction
  991   			return false;
  992   		}
  993   		AutoFlushEvent event = new AutoFlushEvent(querySpaces, this);
  994   		AutoFlushEventListener[] autoFlushEventListener = listeners.getAutoFlushEventListeners();
  995   		for ( int i = 0; i < autoFlushEventListener.length; i++ ) {
  996   			autoFlushEventListener[i].onAutoFlush(event);
  997   		}
  998   		return event.isFlushRequired();
  999   	}
 1000   
 1001   	public boolean isDirty() throws HibernateException {
 1002   		errorIfClosed();
 1003   		checkTransactionSynchStatus();
 1004   		log.debug("checking session dirtiness");
 1005   		if ( actionQueue.areInsertionsOrDeletionsQueued() ) {
 1006   			log.debug("session dirty (scheduled updates and insertions)");
 1007   			return true;
 1008   		}
 1009   		else {
 1010   			DirtyCheckEvent event = new DirtyCheckEvent(this);
 1011   			DirtyCheckEventListener[] dirtyCheckEventListener = listeners.getDirtyCheckEventListeners();
 1012   			for ( int i = 0; i < dirtyCheckEventListener.length; i++ ) {
 1013   				dirtyCheckEventListener[i].onDirtyCheck(event);
 1014   			}
 1015   			return event.isDirty();
 1016   		}
 1017   	}
 1018   
 1019   	public void flush() throws HibernateException {
 1020   		errorIfClosed();
 1021   		checkTransactionSynchStatus();
 1022   		if ( persistenceContext.getCascadeLevel() > 0 ) {
 1023   			throw new HibernateException("Flush during cascade is dangerous");
 1024   		}
 1025   		FlushEventListener[] flushEventListener = listeners.getFlushEventListeners();
 1026   		for ( int i = 0; i < flushEventListener.length; i++ ) {
 1027   			flushEventListener[i].onFlush( new FlushEvent(this) );
 1028   		}
 1029   	}
 1030   
 1031   	public void forceFlush(EntityEntry entityEntry) throws HibernateException {
 1032   		errorIfClosed();
 1033   		if ( log.isDebugEnabled() ) {
 1034   			log.debug(
 1035   				"flushing to force deletion of re-saved object: " +
 1036   				MessageHelper.infoString( entityEntry.getPersister(), entityEntry.getId(), getFactory() )
 1037   			);
 1038   		}
 1039   
 1040   		if ( persistenceContext.getCascadeLevel() > 0 ) {
 1041   			throw new ObjectDeletedException(
 1042   				"deleted object would be re-saved by cascade (remove deleted object from associations)",
 1043   				entityEntry.getId(),
 1044   				entityEntry.getPersister().getEntityName()
 1045   			);
 1046   		}
 1047   
 1048   		flush();
 1049   	}
 1050   
 1051   	public Filter getEnabledFilter(String filterName) {
 1052   		checkTransactionSynchStatus();
 1053   		return (Filter) enabledFilters.get(filterName);
 1054   	}
 1055   
 1056   	public Filter enableFilter(String filterName) {
 1057   		errorIfClosed();
 1058   		checkTransactionSynchStatus();
 1059   		FilterImpl filter = new FilterImpl( factory.getFilterDefinition(filterName) );
 1060   		enabledFilters.put(filterName, filter);
 1061   		return filter;
 1062   	}
 1063   
 1064   	public void disableFilter(String filterName) {
 1065   		errorIfClosed();
 1066   		checkTransactionSynchStatus();
 1067   		enabledFilters.remove(filterName);
 1068   	}
 1069   
 1070   	public Object getFilterParameterValue(String filterParameterName) {
 1071   		errorIfClosed();
 1072   		checkTransactionSynchStatus();
 1073   		String[] parsed = parseFilterParameterName(filterParameterName);
 1074   		FilterImpl filter = (FilterImpl) enabledFilters.get( parsed[0] );
 1075   		if (filter == null) {
 1076   			throw new IllegalArgumentException("Filter [" + parsed[0] + "] currently not enabled");
 1077   		}
 1078   		return filter.getParameter( parsed[1] );
 1079   	}
 1080   
 1081   	public Type getFilterParameterType(String filterParameterName) {
 1082   		errorIfClosed();
 1083   		checkTransactionSynchStatus();
 1084   		String[] parsed = parseFilterParameterName(filterParameterName);
 1085   		FilterDefinition filterDef = factory.getFilterDefinition( parsed[0] );
 1086   		if (filterDef == null) {
 1087   			throw new IllegalArgumentException("Filter [" + parsed[0] + "] not defined");
 1088   		}
 1089   		Type type = filterDef.getParameterType( parsed[1] );
 1090   		if (type == null) {
 1091   			// this is an internal error of some sort...
 1092   			throw new InternalError("Unable to locate type for filter parameter");
 1093   		}
 1094   		return type;
 1095   	}
 1096   
 1097   	public Map getEnabledFilters() {
 1098   		errorIfClosed();
 1099   		checkTransactionSynchStatus();
 1100   		// First, validate all the enabled filters...
 1101   		//TODO: this implementation has bad performance
 1102   		Iterator itr = enabledFilters.values().iterator();
 1103   		while ( itr.hasNext() ) {
 1104   			final Filter filter = (Filter) itr.next();
 1105   			filter.validate();
 1106   		}
 1107   		return enabledFilters;
 1108   	}
 1109   
 1110   	private String[] parseFilterParameterName(String filterParameterName) {
 1111   		int dot = filterParameterName.indexOf('.');
 1112   		if (dot <= 0) {
 1113   			throw new IllegalArgumentException("Invalid filter-parameter name format"); // TODO: what type?
 1114   		}
 1115   		String filterName = filterParameterName.substring(0, dot);
 1116   		String parameterName = filterParameterName.substring(dot+1);
 1117   		return new String[] {filterName, parameterName};
 1118   	}
 1119   
 1120   
 1121   	/**
 1122   	 * Retrieve a list of persistent objects using a hibernate query
 1123   	 */
 1124   	public List find(String query) throws HibernateException {
 1125   		return list( query, new QueryParameters() );
 1126   	}
 1127   
 1128   	public List find(String query, Object value, Type type) throws HibernateException {
 1129   		return list( query, new QueryParameters(type, value) );
 1130   	}
 1131   
 1132   	public List find(String query, Object[] values, Type[] types) throws HibernateException {
 1133   		return list( query, new QueryParameters(types, values) );
 1134   	}
 1135   
 1136   	public List list(String query, QueryParameters queryParameters) throws HibernateException {
 1137   		errorIfClosed();
 1138   		checkTransactionSynchStatus();
 1139   		queryParameters.validateParameters();
 1140   		HQLQueryPlan plan = getHQLQueryPlan( query, false );
 1141   		autoFlushIfRequired( plan.getQuerySpaces() );
 1142   
 1143   		List results = CollectionHelper.EMPTY_LIST;
 1144   		boolean success = false;
 1145   
 1146   		dontFlushFromFind++;   //stops flush being called multiple times if this method is recursively called
 1147   		try {
 1148   			results = plan.performList( queryParameters, this );
 1149   			success = true;
 1150   		}
 1151   		finally {
 1152   			dontFlushFromFind--;
 1153   			afterOperation(success);
 1154   		}
 1155   		return results;
 1156   	}
 1157   
 1158   	public int executeUpdate(String query, QueryParameters queryParameters) throws HibernateException {
 1159   		errorIfClosed();
 1160   		checkTransactionSynchStatus();
 1161   		queryParameters.validateParameters();
 1162   		HQLQueryPlan plan = getHQLQueryPlan( query, false );
 1163   		autoFlushIfRequired( plan.getQuerySpaces() );
 1164   
 1165   		boolean success = false;
 1166   		int result = 0;
 1167   		try {
 1168   			result = plan.performExecuteUpdate( queryParameters, this );
 1169   			success = true;
 1170   		}
 1171   		finally {
 1172   			afterOperation(success);
 1173   		}
 1174   		return result;
 1175   	}
 1176   
 1177       public int executeNativeUpdate(NativeSQLQuerySpecification nativeQuerySpecification,
 1178               QueryParameters queryParameters) throws HibernateException {
 1179           errorIfClosed();
 1180           checkTransactionSynchStatus();
 1181           queryParameters.validateParameters();
 1182           NativeSQLQueryPlan plan = getNativeSQLQueryPlan(nativeQuerySpecification);
 1183   
 1184           
 1185           autoFlushIfRequired( plan.getCustomQuery().getQuerySpaces() );
 1186           
 1187           boolean success = false;
 1188           int result = 0;
 1189           try {
 1190               result = plan.performExecuteUpdate(queryParameters, this);
 1191               success = true;
 1192           } finally {
 1193               afterOperation(success);
 1194           }
 1195           return result;
 1196       }
 1197   
 1198   	public Iterator iterate(String query) throws HibernateException {
 1199   		return iterate( query, new QueryParameters() );
 1200   	}
 1201   
 1202   	public Iterator iterate(String query, Object value, Type type) throws HibernateException {
 1203   		return iterate( query, new QueryParameters(type, value) );
 1204   	}
 1205   
 1206   	public Iterator iterate(String query, Object[] values, Type[] types) throws HibernateException {
 1207   		return iterate( query, new QueryParameters(types, values) );
 1208   	}
 1209   
 1210   	public Iterator iterate(String query, QueryParameters queryParameters) throws HibernateException {
 1211   		errorIfClosed();
 1212   		checkTransactionSynchStatus();
 1213   		queryParameters.validateParameters();
 1214   		HQLQueryPlan plan = getHQLQueryPlan( query, true );
 1215   		autoFlushIfRequired( plan.getQuerySpaces() );
 1216   
 1217   		dontFlushFromFind++; //stops flush being called multiple times if this method is recursively called
 1218   		try {
 1219   			return plan.performIterate( queryParameters, this );
 1220   		}
 1221   		finally {
 1222   			dontFlushFromFind--;
 1223   		}
 1224   	}
 1225   
 1226   	public ScrollableResults scroll(String query, QueryParameters queryParameters) throws HibernateException {
 1227   		errorIfClosed();
 1228   		checkTransactionSynchStatus();
 1229   		HQLQueryPlan plan = getHQLQueryPlan( query, false );
 1230   		autoFlushIfRequired( plan.getQuerySpaces() );
 1231   		dontFlushFromFind++;
 1232   		try {
 1233   			return plan.performScroll( queryParameters, this );
 1234   		}
 1235   		finally {
 1236   			dontFlushFromFind--;
 1237   		}
 1238   	}
 1239   
 1240   	public int delete(String query) throws HibernateException {
 1241   		return delete( query, ArrayHelper.EMPTY_OBJECT_ARRAY, ArrayHelper.EMPTY_TYPE_ARRAY );
 1242   	}
 1243   
 1244   	public int delete(String query, Object value, Type type) throws HibernateException {
 1245   		return delete( query, new Object[]{value}, new Type[]{type} );
 1246   	}
 1247   
 1248   	public int delete(String query, Object[] values, Type[] types) throws HibernateException {
 1249   		errorIfClosed();
 1250   		checkTransactionSynchStatus();
 1251   		if ( query == null ) {
 1252   			throw new IllegalArgumentException("attempt to perform delete-by-query with null query");
 1253   		}
 1254   
 1255   		if ( log.isTraceEnabled() ) {
 1256   			log.trace( "delete: " + query );
 1257   			if ( values.length != 0 ) {
 1258   				log.trace( "parameters: " + StringHelper.toString( values ) );
 1259   			}
 1260   		}
 1261   
 1262   		List list = find( query, values, types );
 1263   		int deletionCount = list.size();
 1264   		for ( int i = 0; i < deletionCount; i++ ) {
 1265   			delete( list.get( i ) );
 1266   		}
 1267   
 1268   		return deletionCount;
 1269   	}
 1270   
 1271   	public Query createFilter(Object collection, String queryString) {
 1272   		errorIfClosed();
 1273   		checkTransactionSynchStatus();
 1274   		CollectionFilterImpl filter = new CollectionFilterImpl(
 1275   				queryString,
 1276   		        collection,
 1277   		        this,
 1278   		        getFilterQueryPlan( collection, queryString, null, false ).getParameterMetadata()
 1279   		);
 1280   		filter.setComment( queryString );
 1281   		return filter;
 1282   	}
 1283   	
 1284   	public Query getNamedQuery(String queryName) throws MappingException {
 1285   		errorIfClosed();
 1286   		checkTransactionSynchStatus();
 1287   		return super.getNamedQuery(queryName);
 1288   	}
 1289   
 1290   	public Object instantiate(String entityName, Serializable id) throws HibernateException {
 1291   		return instantiate( factory.getEntityPersister(entityName), id );
 1292   	}
 1293   
 1294   	/**
 1295   	 * give the interceptor an opportunity to override the default instantiation
 1296   	 */
 1297   	public Object instantiate(EntityPersister persister, Serializable id) throws HibernateException {
 1298   		errorIfClosed();
 1299   		checkTransactionSynchStatus();
 1300   		Object result = interceptor.instantiate( persister.getEntityName(), entityMode, id );
 1301   		if ( result == null ) {
 1302   			result = persister.instantiate( id, entityMode );
 1303   		}
 1304   		return result;
 1305   	}
 1306   
 1307   	public EntityMode getEntityMode() {
 1308   		checkTransactionSynchStatus();
 1309   		return entityMode;
 1310   	}
 1311   
 1312   	public void setFlushMode(FlushMode flushMode) {
 1313   		errorIfClosed();
 1314   		checkTransactionSynchStatus();
 1315   		if ( log.isTraceEnabled() ) {
 1316   			log.trace("setting flush mode to: " + flushMode);
 1317   		}
 1318   		this.flushMode = flushMode;
 1319   	}
 1320   	
 1321   	public FlushMode getFlushMode() {
 1322   		checkTransactionSynchStatus();
 1323   		return flushMode;
 1324   	}
 1325   
 1326   	public CacheMode getCacheMode() {
 1327   		checkTransactionSynchStatus();
 1328   		return cacheMode;
 1329   	}
 1330   	
 1331   	public void setCacheMode(CacheMode cacheMode) {
 1332   		errorIfClosed();
 1333   		checkTransactionSynchStatus();
 1334   		if ( log.isTraceEnabled() ) {
 1335   			log.trace("setting cache mode to: " + cacheMode);
 1336   		}
 1337   		this.cacheMode= cacheMode; 
 1338   	}
 1339   
 1340   	public Transaction getTransaction() throws HibernateException {
 1341   		errorIfClosed();
 1342   		return jdbcContext.getTransaction();
 1343   	}
 1344   	
 1345   	public Transaction beginTransaction() throws HibernateException {
 1346   		errorIfClosed();
 1347   		if ( rootSession != null ) {
 1348   			// todo : should seriously consider not allowing a txn to begin from a child session
 1349   			//      can always route the request to the root session...
 1350   			log.warn( "Transaction started on non-root session" );
 1351   		}
 1352   		Transaction result = getTransaction();
 1353   		result.begin();
 1354   		return result;
 1355   	}
 1356   	
 1357   	public void afterTransactionBegin(Transaction tx) {
 1358   		errorIfClosed();
 1359   		interceptor.afterTransactionBegin(tx);
 1360   	}
 1361   
 1362   	public EntityPersister getEntityPersister(final String entityName, final Object object) {
 1363   		errorIfClosed();
 1364   		if (entityName==null) {
 1365   			return factory.getEntityPersister( guessEntityName( object ) );
 1366   		}
 1367   		else {
 1368   			// try block is a hack around fact that currently tuplizers are not
 1369   			// given the opportunity to resolve a subclass entity name.  this
 1370   			// allows the (we assume custom) interceptor the ability to
 1371   			// influence this decision if we were not able to based on the
 1372   			// given entityName
 1373   			try {
 1374   				return factory.getEntityPersister( entityName )
 1375   						.getSubclassEntityPersister( object, getFactory(), entityMode );
 1376   			}
 1377   			catch( HibernateException e ) {
 1378   				try {
 1379   					return getEntityPersister( null, object );
 1380   				}
 1381   				catch( HibernateException e2 ) {
 1382   					throw e;
 1383   				}
 1384   			}
 1385   		}
 1386   	}
 1387   
 1388   	// not for internal use:
 1389   	public Serializable getIdentifier(Object object) throws HibernateException {
 1390   		errorIfClosed();
 1391   		checkTransactionSynchStatus();
 1392   		if ( object instanceof HibernateProxy ) {
 1393   			LazyInitializer li = ( (HibernateProxy) object ).getHibernateLazyInitializer();
 1394   			if ( li.getSession() != this ) {
 1395   				throw new TransientObjectException( "The proxy was not associated with this session" );
 1396   			}
 1397   			return li.getIdentifier();
 1398   		}
 1399   		else {
 1400   			EntityEntry entry = persistenceContext.getEntry(object);
 1401   			if ( entry == null ) {
 1402   				throw new TransientObjectException( "The instance was not associated with this session" );
 1403   			}
 1404   			return entry.getId();
 1405   		}
 1406   	}
 1407   
 1408   	/**
 1409   	 * Get the id value for an object that is actually associated with the session. This
 1410   	 * is a bit stricter than getEntityIdentifierIfNotUnsaved().
 1411   	 */
 1412   	public Serializable getContextEntityIdentifier(Object object) {
 1413   		errorIfClosed();
 1414   		if ( object instanceof HibernateProxy ) {
 1415   			return getProxyIdentifier(object);
 1416   		}
 1417   		else {
 1418   			EntityEntry entry = persistenceContext.getEntry(object);
 1419   			return entry != null ? entry.getId() : null;
 1420   		}
 1421   	}
 1422   	
 1423   	private Serializable getProxyIdentifier(Object proxy) {
 1424   		return ( (HibernateProxy) proxy ).getHibernateLazyInitializer().getIdentifier();
 1425   	}
 1426   
 1427   	public Collection filter(Object collection, String filter) throws HibernateException {
 1428   		return listFilter( collection, filter, new QueryParameters( new Type[1], new Object[1] ) );
 1429   	}
 1430   
 1431   	public Collection filter(Object collection, String filter, Object value, Type type) throws HibernateException {
 1432   		return listFilter( collection, filter, new QueryParameters( new Type[]{null, type}, new Object[]{null, value} ) );
 1433   	}
 1434   
 1435   	public Collection filter(Object collection, String filter, Object[] values, Type[] types) 
 1436   	throws HibernateException {
 1437   		Object[] vals = new Object[values.length + 1];
 1438   		Type[] typs = new Type[types.length + 1];
 1439   		System.arraycopy( values, 0, vals, 1, values.length );
 1440   		System.arraycopy( types, 0, typs, 1, types.length );
 1441   		return listFilter( collection, filter, new QueryParameters( typs, vals ) );
 1442   	}
 1443   
 1444   	private FilterQueryPlan getFilterQueryPlan(
 1445   			Object collection,
 1446   			String filter,
 1447   			QueryParameters parameters,
 1448   			boolean shallow) throws HibernateException {
 1449   		if ( collection == null ) {
 1450   			throw new NullPointerException( "null collection passed to filter" );
 1451   		}
 1452   
 1453   		CollectionEntry entry = persistenceContext.getCollectionEntryOrNull( collection );
 1454   		final CollectionPersister roleBeforeFlush = (entry == null) ? null : entry.getLoadedPersister();
 1455   
 1456   		FilterQueryPlan plan = null;
 1457   		if ( roleBeforeFlush == null ) {
 1458   			// if it was previously unreferenced, we need to flush in order to
 1459   			// get its state into the database in order to execute query
 1460   			flush();
 1461   			entry = persistenceContext.getCollectionEntryOrNull( collection );
 1462   			CollectionPersister roleAfterFlush = (entry == null) ? null : entry.getLoadedPersister();
 1463   			if ( roleAfterFlush == null ) {
 1464   				throw new QueryException( "The collection was unreferenced" );
 1465   			}
 1466   			plan = factory.getQueryPlanCache().getFilterQueryPlan( filter, roleAfterFlush.getRole(), shallow, getEnabledFilters() );
 1467   		}
 1468   		else {
 1469   			// otherwise, we only need to flush if there are in-memory changes
 1470   			// to the queried tables
 1471   			plan = factory.getQueryPlanCache().getFilterQueryPlan( filter, roleBeforeFlush.getRole(), shallow, getEnabledFilters() );
 1472   			if ( autoFlushIfRequired( plan.getQuerySpaces() ) ) {
 1473   				// might need to run a different filter entirely after the flush
 1474   				// because the collection role may have changed
 1475   				entry = persistenceContext.getCollectionEntryOrNull( collection );
 1476   				CollectionPersister roleAfterFlush = (entry == null) ? null : entry.getLoadedPersister();
 1477   				if ( roleBeforeFlush != roleAfterFlush ) {
 1478   					if ( roleAfterFlush == null ) {
 1479   						throw new QueryException( "The collection was dereferenced" );
 1480   					}
 1481   					plan = factory.getQueryPlanCache().getFilterQueryPlan( filter, roleAfterFlush.getRole(), shallow, getEnabledFilters() );
 1482   				}
 1483   			}
 1484   		}
 1485   
 1486   		if ( parameters != null ) {
 1487   			parameters.getPositionalParameterValues()[0] = entry.getLoadedKey();
 1488   			parameters.getPositionalParameterTypes()[0] = entry.getLoadedPersister().getKeyType();
 1489   		}
 1490   
 1491   		return plan;
 1492   	}
 1493   
 1494   	public List listFilter(Object collection, String filter, QueryParameters queryParameters) 
 1495   	throws HibernateException {
 1496   		errorIfClosed();
 1497   		checkTransactionSynchStatus();
 1498   		FilterQueryPlan plan = getFilterQueryPlan( collection, filter, queryParameters, false );
 1499   		List results = CollectionHelper.EMPTY_LIST;
 1500   
 1501   		boolean success = false;
 1502   		dontFlushFromFind++;   //stops flush being called multiple times if this method is recursively called
 1503   		try {
 1504   			results = plan.performList( queryParameters, this );
 1505   			success = true;
 1506   		}
 1507   		finally {
 1508   			dontFlushFromFind--;
 1509   			afterOperation(success);
 1510   		}
 1511   		return results;
 1512   	}
 1513   
 1514   	public Iterator iterateFilter(Object collection, String filter, QueryParameters queryParameters) 
 1515   	throws HibernateException {
 1516   		errorIfClosed();
 1517   		checkTransactionSynchStatus();
 1518   		FilterQueryPlan plan = getFilterQueryPlan( collection, filter, queryParameters, true );
 1519   		return plan.performIterate( queryParameters, this );
 1520   	}
 1521   
 1522   	public Criteria createCriteria(Class persistentClass, String alias) {
 1523   		errorIfClosed();
 1524   		checkTransactionSynchStatus();
 1525   		return new CriteriaImpl( persistentClass.getName(), alias, this );
 1526   	}
 1527   
 1528   	public Criteria createCriteria(String entityName, String alias) {
 1529   		errorIfClosed();
 1530   		checkTransactionSynchStatus();
 1531   		return new CriteriaImpl(entityName, alias, this);
 1532   	}
 1533   
 1534   	public Criteria createCriteria(Class persistentClass) {
 1535   		errorIfClosed();
 1536   		checkTransactionSynchStatus();
 1537   		return new CriteriaImpl( persistentClass.getName(), this );
 1538   	}
 1539   
 1540   	public Criteria createCriteria(String entityName) {
 1541   		errorIfClosed();
 1542   		checkTransactionSynchStatus();
 1543   		return new CriteriaImpl(entityName, this);
 1544   	}
 1545   
 1546   	public ScrollableResults scroll(CriteriaImpl criteria, ScrollMode scrollMode) {
 1547   		errorIfClosed();
 1548   		checkTransactionSynchStatus();
 1549   		String entityName = criteria.getEntityOrClassName();
 1550   		CriteriaLoader loader = new CriteriaLoader(
 1551   				getOuterJoinLoadable(entityName),
 1552   				factory,
 1553   				criteria,
 1554   				entityName,
 1555   				getEnabledFilters()
 1556   		);
 1557   		autoFlushIfRequired( loader.getQuerySpaces() );
 1558   		dontFlushFromFind++;
 1559   		try {
 1560   			return loader.scroll(this, scrollMode);
 1561   		}
 1562   		finally {
 1563   			dontFlushFromFind--;
 1564   		}
 1565   	}
 1566   
 1567   	public List list(CriteriaImpl criteria) throws HibernateException {
 1568   		errorIfClosed();
 1569   		checkTransactionSynchStatus();
 1570   		String[] implementors = factory.getImplementors( criteria.getEntityOrClassName() );
 1571   		int size = implementors.length;
 1572   
 1573   		CriteriaLoader[] loaders = new CriteriaLoader[size];
 1574   		Set spaces = new HashSet();
 1575   		for( int i=0; i <size; i++ ) {
 1576   
 1577   			loaders[i] = new CriteriaLoader(
 1578   					getOuterJoinLoadable( implementors[i] ),
 1579   					factory,
 1580   					criteria,
 1581   					implementors[i],
 1582   					getEnabledFilters()
 1583   				);
 1584   
 1585   			spaces.addAll( loaders[i].getQuerySpaces() );
 1586   
 1587   		}
 1588   
 1589   		autoFlushIfRequired(spaces);
 1590   
 1591   		List results = Collections.EMPTY_LIST;
 1592   		dontFlushFromFind++;
 1593   		boolean success = false;
 1594   		try {
 1595   			for( int i=0; i<size; i++ ) {
 1596   				final List currentResults = loaders[i].list(this);
 1597   				currentResults.addAll(results);
 1598   				results = currentResults;
 1599   			}
 1600   			success = true;
 1601   		}
 1602   		finally {
 1603   			dontFlushFromFind--;
 1604   			afterOperation(success);
 1605   		}
 1606   
 1607   		return results;
 1608   	}
 1609   
 1610   	private OuterJoinLoadable getOuterJoinLoadable(String entityName) throws MappingException {
 1611   		EntityPersister persister = factory.getEntityPersister(entityName);
 1612   		if ( !(persister instanceof OuterJoinLoadable) ) {
 1613   			throw new MappingException( "class persister is not OuterJoinLoadable: " + entityName );
 1614   		}
 1615   		return ( OuterJoinLoadable ) persister;
 1616   	}
 1617   
 1618   	public boolean contains(Object object) {
 1619   		errorIfClosed();
 1620   		checkTransactionSynchStatus();
 1621   		if ( object instanceof HibernateProxy ) {
 1622   			//do not use proxiesByKey, since not all
 1623   			//proxies that point to this session's
 1624   			//instances are in that collection!
 1625   			LazyInitializer li = ( (HibernateProxy) object ).getHibernateLazyInitializer();
 1626   			if ( li.isUninitialized() ) {
 1627   				//if it is an uninitialized proxy, pointing
 1628   				//with this session, then when it is accessed,
 1629   				//the underlying instance will be "contained"
 1630   				return li.getSession()==this;
 1631   			}
 1632   			else {
 1633   				//if it is initialized, see if the underlying
 1634   				//instance is contained, since we need to 
 1635   				//account for the fact that it might have been
 1636   				//evicted
 1637   				object = li.getImplementation();
 1638   			}
 1639   		}
 1640   		// A session is considered to contain an entity only if the entity has
 1641   		// an entry in the session's persistence context and the entry reports
 1642   		// that the entity has not been removed
 1643   		EntityEntry entry = persistenceContext.getEntry( object );
 1644   		return entry != null && entry.getStatus() != Status.DELETED && entry.getStatus() != Status.GONE;
 1645   	}
 1646   	
 1647   	public Query createQuery(String queryString) {
 1648   		errorIfClosed();
 1649   		checkTransactionSynchStatus();
 1650   		return super.createQuery(queryString);
 1651   	}
 1652   	
 1653   	public SQLQuery createSQLQuery(String sql) {
 1654   		errorIfClosed();
 1655   		checkTransactionSynchStatus();
 1656   		return super.createSQLQuery(sql);
 1657   	}
 1658   
 1659   	public Query createSQLQuery(String sql, String returnAlias, Class returnClass) {
 1660   		errorIfClosed();
 1661   		checkTransactionSynchStatus();
 1662   		return new SQLQueryImpl(
 1663   				sql,
 1664   		        new String[] { returnAlias },
 1665   		        new Class[] { returnClass },
 1666   		        this,
 1667   		        factory.getQueryPlanCache().getSQLParameterMetadata( sql )
 1668   		);
 1669   	}
 1670   
 1671   	public Query createSQLQuery(String sql, String returnAliases[], Class returnClasses[]) {
 1672   		errorIfClosed();
 1673   		checkTransactionSynchStatus();
 1674   		return new SQLQueryImpl(
 1675   				sql,
 1676   		        returnAliases,
 1677   		        returnClasses,
 1678   		        this,
 1679   		        factory.getQueryPlanCache().getSQLParameterMetadata( sql )
 1680   		);
 1681   	}
 1682   
 1683   	public ScrollableResults scrollCustomQuery(CustomQuery customQuery, QueryParameters queryParameters) 
 1684   	throws HibernateException {
 1685   		errorIfClosed();
 1686   		checkTransactionSynchStatus();
 1687   
 1688   		if ( log.isTraceEnabled() ) {
 1689   			log.trace( "scroll SQL query: " + customQuery.getSQL() );
 1690   		}
 1691   
 1692   		CustomLoader loader = new CustomLoader( customQuery, getFactory() );
 1693   
 1694   		autoFlushIfRequired( loader.getQuerySpaces() );
 1695   
 1696   		dontFlushFromFind++; //stops flush being called multiple times if this method is recursively called
 1697   		try {
 1698   			return loader.scroll(queryParameters, this);
 1699   		}
 1700   		finally {
 1701   			dontFlushFromFind--;
 1702   		}
 1703   	}
 1704   
 1705   	// basically just an adapted copy of find(CriteriaImpl)
 1706   	public List listCustomQuery(CustomQuery customQuery, QueryParameters queryParameters) 
 1707   	throws HibernateException {
 1708   		errorIfClosed();
 1709   		checkTransactionSynchStatus();
 1710   
 1711   		if ( log.isTraceEnabled() ) {
 1712   			log.trace( "SQL query: " + customQuery.getSQL() );
 1713   		}
 1714   		
 1715   		CustomLoader loader = new CustomLoader( customQuery, getFactory() );
 1716   
 1717   		autoFlushIfRequired( loader.getQuerySpaces() );
 1718   
 1719   		dontFlushFromFind++;
 1720   		boolean success = false;
 1721   		try {
 1722   			List results = loader.list(this, queryParameters);
 1723   			success = true;
 1724   			return results;
 1725   		}
 1726   		finally {
 1727   			dontFlushFromFind--;
 1728   			afterOperation(success);
 1729   		}
 1730   	}
 1731   
 1732   	public SessionFactory getSessionFactory() {
 1733   		checkTransactionSynchStatus();
 1734   		return factory;
 1735   	}
 1736   	
 1737   	public void initializeCollection(PersistentCollection collection, boolean writing) 
 1738   	throws HibernateException {
 1739   		errorIfClosed();
 1740   		checkTransactionSynchStatus();
 1741   		InitializeCollectionEventListener[] listener = listeners.getInitializeCollectionEventListeners();
 1742   		for ( int i = 0; i < listener.length; i++ ) {
 1743   			listener[i].onInitializeCollection( new InitializeCollectionEvent(collection, this) );
 1744   		}
 1745   	}
 1746   
 1747   	public String bestGuessEntityName(Object object) {
 1748   		if (object instanceof HibernateProxy) {
 1749   			LazyInitializer initializer = ( ( HibernateProxy ) object ).getHibernateLazyInitializer();
 1750   			// it is possible for this method to be called during flush processing,
 1751   			// so make certain that we do not accidently initialize an uninitialized proxy
 1752   			if ( initializer.isUninitialized() ) {
 1753   				return initializer.getEntityName();
 1754   			}
 1755   			object = initializer.getImplementation();
 1756   		}
 1757   		EntityEntry entry = persistenceContext.getEntry(object);
 1758   		if (entry==null) {
 1759   			return guessEntityName(object);
 1760   		}
 1761   		else {
 1762   			return entry.getPersister().getEntityName();
 1763   		}
 1764   	}
 1765   	
 1766   	public String getEntityName(Object object) {
 1767   		errorIfClosed();
 1768   		checkTransactionSynchStatus();
 1769   		if (object instanceof HibernateProxy) {
 1770   			if ( !persistenceContext.containsProxy( object ) ) {
 1771   				throw new TransientObjectException("proxy was not associated with the session");
 1772   			}
 1773   			object = ( (HibernateProxy) object ).getHibernateLazyInitializer().getImplementation();
 1774   		}
 1775   
 1776   		EntityEntry entry = persistenceContext.getEntry(object);
 1777   		if ( entry == null ) {
 1778   			throwTransientObjectException( object );
 1779   		}
 1780   		return entry.getPersister().getEntityName();
 1781   	}
 1782   
 1783   	private void throwTransientObjectException(Object object) throws HibernateException {
 1784   		throw new TransientObjectException(
 1785   				"object references an unsaved transient instance - save the transient instance before flushing: " +
 1786   				guessEntityName(object)
 1787   			);
 1788   	}
 1789   
 1790   	public String guessEntityName(Object object) throws HibernateException {
 1791   		errorIfClosed();
 1792   		String entity = interceptor.getEntityName( object );
 1793   		if ( entity == null ) {
 1794   			if ( object instanceof Map ) {
 1795   				entity = (String) ( (Map) object ).get( DynamicMapInstantiator.KEY );
 1796   				if ( entity == null ) {
 1797   					throw new HibernateException( "could not determine type of dynamic entity" );
 1798   				}
 1799   			}
 1800   			else if ( object instanceof Element ) {
 1801   				// TODO : really need to keep a map of nodeName -> entityName, but that would mean nodeName being distinct
 1802   				entity = ( (Element) object ).getName();
 1803   			}
 1804   			else {
 1805   				entity = object.getClass().getName();
 1806   			}
 1807   		}
 1808   		return entity;
 1809   	}
 1810   
 1811   	public void cancelQuery() throws HibernateException {
 1812   		errorIfClosed();
 1813   		getBatcher().cancelLastQuery();
 1814   	}
 1815   
 1816   	public Interceptor getInterceptor() {
 1817   		checkTransactionSynchStatus();
 1818   		return interceptor;
 1819   	}
 1820   
 1821   	public int getDontFlushFromFind() {
 1822   		return dontFlushFromFind;
 1823   	}
 1824   
 1825   	public String toString() {
 1826   		StringBuffer buf = new StringBuffer(500)
 1827   			.append( "SessionImpl(" );
 1828   		if ( !isClosed() ) {
 1829   			buf.append(persistenceContext)
 1830   				.append(";")
 1831   				.append(actionQueue);
 1832   		}
 1833   		else {
 1834   			buf.append("<closed>");
 1835   		}
 1836   		return buf.append(')').toString();
 1837   	}
 1838   
 1839   	public EventListeners getListeners() {
 1840   		return listeners;
 1841   	}
 1842   
 1843   	public ActionQueue getActionQueue() {
 1844   		errorIfClosed();
 1845   		checkTransactionSynchStatus();
 1846   		return actionQueue;
 1847   	}
 1848   	
 1849   	public PersistenceContext getPersistenceContext() {
 1850   		errorIfClosed();
 1851   		checkTransactionSynchStatus();
 1852   		return persistenceContext;
 1853   	}
 1854   	
 1855   	public SessionStatistics getStatistics() {
 1856   		checkTransactionSynchStatus();
 1857   		return new SessionStatisticsImpl(this);
 1858   	}
 1859   
 1860   	public boolean isEventSource() {
 1861   		checkTransactionSynchStatus();
 1862   		return true;
 1863   	}
 1864   
 1865   	public void setReadOnly(Object entity, boolean readOnly) {
 1866   		errorIfClosed();
 1867   		checkTransactionSynchStatus();
 1868   		persistenceContext.setReadOnly(entity, readOnly);
 1869   	}
 1870   
 1871   	public void doWork(Work work) throws HibernateException {
 1872   		try {
 1873   			work.execute( jdbcContext.getConnectionManager().getConnection() );
 1874   			jdbcContext.getConnectionManager().afterStatement();
 1875   		}
 1876   		catch ( SQLException e ) {
 1877   			throw JDBCExceptionHelper.convert( factory.getSettings().getSQLExceptionConverter(), e, "error executing work" );
 1878   		}
 1879   	}
 1880   
 1881   	public void afterScrollOperation() {
 1882   		// nothing to do in a stateful session
 1883   	}
 1884   
 1885   	public String getFetchProfile() {
 1886   		checkTransactionSynchStatus();
 1887   		return fetchProfile;
 1888   	}
 1889   
 1890   	public JDBCContext getJDBCContext() {
 1891   		errorIfClosed();
 1892   		checkTransactionSynchStatus();
 1893   		return jdbcContext;
 1894   	}
 1895   
 1896   	public void setFetchProfile(String fetchProfile) {
 1897   		errorIfClosed();
 1898   		checkTransactionSynchStatus();
 1899   		this.fetchProfile = fetchProfile;
 1900   	}
 1901   
 1902   	private void checkTransactionSynchStatus() {
 1903   		if ( jdbcContext != null && !isClosed() ) {
 1904   			jdbcContext.registerSynchronizationIfPossible();
 1905   		}
 1906   	}
 1907   
 1908   	/**
 1909   	 * Used by JDK serialization...
 1910   	 *
 1911   	 * @param ois The input stream from which we are being read...
 1912   	 * @throws IOException Indicates a general IO stream exception
 1913   	 * @throws ClassNotFoundException Indicates a class resolution issue
 1914   	 */
 1915   	private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
 1916   		log.trace( "deserializing session" );
 1917   
 1918   		boolean isRootSession = ois.readBoolean();
 1919   		connectionReleaseMode = ConnectionReleaseMode.parse( ( String ) ois.readObject() );
 1920   		entityMode = EntityMode.parse( ( String ) ois.readObject() );
 1921   		autoClear = ois.readBoolean();
 1922   		flushMode = FlushMode.parse( ( String ) ois.readObject() );
 1923   		cacheMode = CacheMode.parse( ( String ) ois.readObject() );
 1924   		flushBeforeCompletionEnabled = ois.readBoolean();
 1925   		autoCloseSessionEnabled = ois.readBoolean();
 1926   		fetchProfile = ( String ) ois.readObject();
 1927   		interceptor = ( Interceptor ) ois.readObject();
 1928   
 1929   		factory = SessionFactoryImpl.deserialize( ois );
 1930   		listeners = factory.getEventListeners();
 1931   
 1932   		if ( isRootSession ) {
 1933   			jdbcContext = JDBCContext.deserialize( ois, this, interceptor );
 1934   		}
 1935   
 1936   		persistenceContext = StatefulPersistenceContext.deserialize( ois, this );
 1937   		actionQueue = ActionQueue.deserialize( ois, this );
 1938   
 1939   		enabledFilters = ( Map ) ois.readObject();
 1940   		childSessionsByEntityMode = ( Map ) ois.readObject();
 1941   
 1942   		Iterator iter = enabledFilters.values().iterator();
 1943   		while ( iter.hasNext() ) {
 1944   			( ( FilterImpl ) iter.next() ).afterDeserialize(factory);
 1945   		}
 1946   
 1947   		if ( isRootSession && childSessionsByEntityMode != null ) {
 1948   			iter = childSessionsByEntityMode.values().iterator();
 1949   			while ( iter.hasNext() ) {
 1950   				final SessionImpl child = ( ( SessionImpl ) iter.next() );
 1951   				child.rootSession = this;
 1952   				child.jdbcContext = this.jdbcContext;
 1953   			}
 1954   		}
 1955   	}
 1956   
 1957   	/**
 1958   	 * Used by JDK serialization...
 1959   	 *
 1960   	 * @param oos The output stream to which we are being written...
 1961   	 * @throws IOException Indicates a general IO stream exception
 1962   	 */
 1963   	private void writeObject(ObjectOutputStream oos) throws IOException {
 1964   		if ( !jdbcContext.getConnectionManager().isReadyForSerialization() ) {
 1965   			throw new IllegalStateException( "Cannot serialize a session while connected" );
 1966   		}
 1967   
 1968   		log.trace( "serializing session" );
 1969   
 1970   		oos.writeBoolean( rootSession == null );
 1971   		oos.writeObject( connectionReleaseMode.toString() );
 1972   		oos.writeObject( entityMode.toString() );
 1973   		oos.writeBoolean( autoClear );
 1974   		oos.writeObject( flushMode.toString() );
 1975   		oos.writeObject( cacheMode.toString() );
 1976   		oos.writeBoolean( flushBeforeCompletionEnabled );
 1977   		oos.writeBoolean( autoCloseSessionEnabled );
 1978   		oos.writeObject( fetchProfile );
 1979   		// we need to writeObject() on this since interceptor is user defined
 1980   		oos.writeObject( interceptor );
 1981   
 1982   		factory.serialize( oos );
 1983   
 1984   		if ( rootSession == null ) {
 1985   			jdbcContext.serialize( oos );
 1986   		}
 1987   
 1988   		persistenceContext.serialize( oos );
 1989   		actionQueue.serialize( oos );
 1990   
 1991   		// todo : look at optimizing these...
 1992   		oos.writeObject( enabledFilters );
 1993   		oos.writeObject( childSessionsByEntityMode );
 1994   	}
 1995   }

Save This Page
Home » hibernate-distribution-3.3.1.GA-dist » org.hibernate » impl » [javadoc | source]