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.InvalidObjectException;
   29   import java.io.ObjectInputStream;
   30   import java.io.ObjectOutputStream;
   31   import java.io.ObjectStreamException;
   32   import java.io.Serializable;
   33   import java.sql.Connection;
   34   import java.util.ArrayList;
   35   import java.util.Collections;
   36   import java.util.HashMap;
   37   import java.util.HashSet;
   38   import java.util.Iterator;
   39   import java.util.Map;
   40   import java.util.Properties;
   41   import java.util.Set;
   42   import javax.naming.NamingException;
   43   import javax.naming.Reference;
   44   import javax.naming.StringRefAddr;
   45   import javax.transaction.TransactionManager;
   46   
   47   import org.slf4j.Logger;
   48   import org.slf4j.LoggerFactory;
   49   
   50   import org.hibernate.AssertionFailure;
   51   import org.hibernate.ConnectionReleaseMode;
   52   import org.hibernate.EntityMode;
   53   import org.hibernate.HibernateException;
   54   import org.hibernate.Interceptor;
   55   import org.hibernate.MappingException;
   56   import org.hibernate.ObjectNotFoundException;
   57   import org.hibernate.QueryException;
   58   import org.hibernate.SessionFactory;
   59   import org.hibernate.StatelessSession;
   60   import org.hibernate.SessionFactoryObserver;
   61   import org.hibernate.cache.CacheKey;
   62   import org.hibernate.cache.CollectionRegion;
   63   import org.hibernate.cache.EntityRegion;
   64   import org.hibernate.cache.QueryCache;
   65   import org.hibernate.cache.Region;
   66   import org.hibernate.cache.UpdateTimestampsCache;
   67   import org.hibernate.cache.access.AccessType;
   68   import org.hibernate.cache.access.CollectionRegionAccessStrategy;
   69   import org.hibernate.cache.access.EntityRegionAccessStrategy;
   70   import org.hibernate.cache.impl.CacheDataDescriptionImpl;
   71   import org.hibernate.cfg.Configuration;
   72   import org.hibernate.cfg.Environment;
   73   import org.hibernate.cfg.Settings;
   74   import org.hibernate.connection.ConnectionProvider;
   75   import org.hibernate.context.CurrentSessionContext;
   76   import org.hibernate.context.JTASessionContext;
   77   import org.hibernate.context.ManagedSessionContext;
   78   import org.hibernate.context.ThreadLocalSessionContext;
   79   import org.hibernate.dialect.Dialect;
   80   import org.hibernate.dialect.function.SQLFunctionRegistry;
   81   import org.hibernate.engine.FilterDefinition;
   82   import org.hibernate.engine.Mapping;
   83   import org.hibernate.engine.NamedQueryDefinition;
   84   import org.hibernate.engine.NamedSQLQueryDefinition;
   85   import org.hibernate.engine.ResultSetMappingDefinition;
   86   import org.hibernate.engine.SessionFactoryImplementor;
   87   import org.hibernate.engine.query.QueryPlanCache;
   88   import org.hibernate.engine.query.sql.NativeSQLQuerySpecification;
   89   import org.hibernate.event.EventListeners;
   90   import org.hibernate.exception.SQLExceptionConverter;
   91   import org.hibernate.id.IdentifierGenerator;
   92   import org.hibernate.id.UUIDHexGenerator;
   93   import org.hibernate.jdbc.BatcherFactory;
   94   import org.hibernate.mapping.Collection;
   95   import org.hibernate.mapping.PersistentClass;
   96   import org.hibernate.mapping.RootClass;
   97   import org.hibernate.metadata.ClassMetadata;
   98   import org.hibernate.metadata.CollectionMetadata;
   99   import org.hibernate.persister.PersisterFactory;
  100   import org.hibernate.persister.collection.CollectionPersister;
  101   import org.hibernate.persister.entity.EntityPersister;
  102   import org.hibernate.persister.entity.Queryable;
  103   import org.hibernate.pretty.MessageHelper;
  104   import org.hibernate.proxy.EntityNotFoundDelegate;
  105   import org.hibernate.stat.Statistics;
  106   import org.hibernate.stat.StatisticsImpl;
  107   import org.hibernate.stat.StatisticsImplementor;
  108   import org.hibernate.tool.hbm2ddl.SchemaExport;
  109   import org.hibernate.tool.hbm2ddl.SchemaUpdate;
  110   import org.hibernate.tool.hbm2ddl.SchemaValidator;
  111   import org.hibernate.transaction.TransactionFactory;
  112   import org.hibernate.type.AssociationType;
  113   import org.hibernate.type.Type;
  114   import org.hibernate.util.CollectionHelper;
  115   import org.hibernate.util.ReflectHelper;
  116   
  117   
  118   /**
  119    * Concrete implementation of the <tt>SessionFactory</tt> interface. Has the following
  120    * responsibilites
  121    * <ul>
  122    * <li>caches configuration settings (immutably)
  123    * <li>caches "compiled" mappings ie. <tt>EntityPersister</tt>s and
  124    *     <tt>CollectionPersister</tt>s (immutable)
  125    * <li>caches "compiled" queries (memory sensitive cache)
  126    * <li>manages <tt>PreparedStatement</tt>s
  127    * <li> delegates JDBC <tt>Connection</tt> management to the <tt>ConnectionProvider</tt>
  128    * <li>factory for instances of <tt>SessionImpl</tt>
  129    * </ul>
  130    * This class must appear immutable to clients, even if it does all kinds of caching
  131    * and pooling under the covers. It is crucial that the class is not only thread
  132    * safe, but also highly concurrent. Synchronization must be used extremely sparingly.
  133    *
  134    * @see org.hibernate.connection.ConnectionProvider
  135    * @see org.hibernate.classic.Session
  136    * @see org.hibernate.hql.QueryTranslator
  137    * @see org.hibernate.persister.entity.EntityPersister
  138    * @see org.hibernate.persister.collection.CollectionPersister
  139    * @author Gavin King
  140    */
  141   public final class SessionFactoryImpl implements SessionFactory, SessionFactoryImplementor {
  142   
  143   	private static final Logger log = LoggerFactory.getLogger(SessionFactoryImpl.class);
  144   	private static final IdentifierGenerator UUID_GENERATOR = new UUIDHexGenerator();
  145   
  146   	private final String name;
  147   	private final String uuid;
  148   
  149   	private final transient Map entityPersisters;
  150   	private final transient Map classMetadata;
  151   	private final transient Map collectionPersisters;
  152   	private final transient Map collectionMetadata;
  153   	private final transient Map collectionRolesByEntityParticipant;
  154   	private final transient Map identifierGenerators;
  155   	private final transient Map namedQueries;
  156   	private final transient Map namedSqlQueries;
  157   	private final transient Map sqlResultSetMappings;
  158   	private final transient Map filters;
  159   	private final transient Map imports;
  160   	private final transient Interceptor interceptor;
  161   	private final transient Settings settings;
  162   	private final transient Properties properties;
  163   	private transient SchemaExport schemaExport;
  164   	private final transient TransactionManager transactionManager;
  165   	private final transient QueryCache queryCache;
  166   	private final transient UpdateTimestampsCache updateTimestampsCache;
  167   	private final transient Map queryCaches;
  168   	private final transient Map allCacheRegions = new HashMap();
  169   	private final transient StatisticsImpl statistics = new StatisticsImpl(this);
  170   	private final transient EventListeners eventListeners;
  171   	private final transient CurrentSessionContext currentSessionContext;
  172   	private final transient EntityNotFoundDelegate entityNotFoundDelegate;
  173   	private final transient SQLFunctionRegistry sqlFunctionRegistry;
  174   	private final transient SessionFactoryObserver observer;
  175   
  176   	private final QueryPlanCache queryPlanCache = new QueryPlanCache( this );
  177   
  178   	private transient boolean isClosed = false;
  179   
  180   	public SessionFactoryImpl(
  181   			Configuration cfg,
  182   	        Mapping mapping,
  183   	        Settings settings,
  184   	        EventListeners listeners,
  185   			SessionFactoryObserver observer) throws HibernateException {
  186   
  187   		log.info("building session factory");
  188   
  189   		this.properties = new Properties();
  190   		this.properties.putAll( cfg.getProperties() );
  191   		this.interceptor = cfg.getInterceptor();
  192   		this.settings = settings;
  193   		this.sqlFunctionRegistry = new SQLFunctionRegistry(settings.getDialect(), cfg.getSqlFunctions());
  194           this.eventListeners = listeners;
  195   		this.observer = observer != null ? observer : new SessionFactoryObserver() {
  196   			public void sessionFactoryCreated(SessionFactory factory) {
  197   			}
  198   			public void sessionFactoryClosed(SessionFactory factory) {
  199   			}
  200   		};
  201   		this.filters = new HashMap();
  202   		this.filters.putAll( cfg.getFilterDefinitions() );
  203   
  204   		if ( log.isDebugEnabled() ) {
  205   			log.debug("Session factory constructed with filter configurations : " + filters);
  206   		}
  207   
  208   		if ( log.isDebugEnabled() ) {
  209   			log.debug(
  210   					"instantiating session factory with properties: " + properties
  211   			);
  212   		}
  213   
  214   		// Caches
  215   		settings.getRegionFactory().start( settings, properties );
  216   
  217   		//Generators:
  218   
  219   		identifierGenerators = new HashMap();
  220   		Iterator classes = cfg.getClassMappings();
  221   		while ( classes.hasNext() ) {
  222   			PersistentClass model = (PersistentClass) classes.next();
  223   			if ( !model.isInherited() ) {
  224   				IdentifierGenerator generator = model.getIdentifier().createIdentifierGenerator(
  225   						settings.getDialect(),
  226   				        settings.getDefaultCatalogName(),
  227   				        settings.getDefaultSchemaName(),
  228   				        (RootClass) model
  229   					);
  230   				identifierGenerators.put( model.getEntityName(), generator );
  231   			}
  232   		}
  233   
  234   
  235   		///////////////////////////////////////////////////////////////////////
  236   		// Prepare persisters and link them up with their cache
  237   		// region/access-strategy
  238   
  239   		final String cacheRegionPrefix = settings.getCacheRegionPrefix() == null ? "" : settings.getCacheRegionPrefix() + ".";
  240   
  241   		entityPersisters = new HashMap();
  242   		Map entityAccessStrategies = new HashMap();
  243   		Map classMeta = new HashMap();
  244   		classes = cfg.getClassMappings();
  245   		while ( classes.hasNext() ) {
  246   			final PersistentClass model = (PersistentClass) classes.next();
  247   			model.prepareTemporaryTables( mapping, settings.getDialect() );
  248   			final String cacheRegionName = cacheRegionPrefix + model.getRootClass().getCacheRegionName();
  249   			// cache region is defined by the root-class in the hierarchy...
  250   			EntityRegionAccessStrategy accessStrategy = ( EntityRegionAccessStrategy ) entityAccessStrategies.get( cacheRegionName );
  251   			if ( accessStrategy == null && settings.isSecondLevelCacheEnabled() ) {
  252   				final AccessType accessType = AccessType.parse( model.getCacheConcurrencyStrategy() );
  253   				if ( accessType != null ) {
  254   					log.trace( "Building cache for entity data [" + model.getEntityName() + "]" );
  255   					EntityRegion entityRegion = settings.getRegionFactory().buildEntityRegion( cacheRegionName, properties, CacheDataDescriptionImpl.decode( model ) );
  256   					accessStrategy = entityRegion.buildAccessStrategy( accessType );
  257   					entityAccessStrategies.put( cacheRegionName, accessStrategy );
  258   					allCacheRegions.put( cacheRegionName, entityRegion );
  259   				}
  260   			}
  261   			EntityPersister cp = PersisterFactory.createClassPersister( model, accessStrategy, this, mapping );
  262   			entityPersisters.put( model.getEntityName(), cp );
  263   			classMeta.put( model.getEntityName(), cp.getClassMetadata() );
  264   		}
  265   		classMetadata = Collections.unmodifiableMap(classMeta);
  266   
  267   		Map tmpEntityToCollectionRoleMap = new HashMap();
  268   		collectionPersisters = new HashMap();
  269   		Iterator collections = cfg.getCollectionMappings();
  270   		while ( collections.hasNext() ) {
  271   			Collection model = (Collection) collections.next();
  272   			final String cacheRegionName = cacheRegionPrefix + model.getCacheRegionName();
  273   			final AccessType accessType = AccessType.parse( model.getCacheConcurrencyStrategy() );
  274   			CollectionRegionAccessStrategy accessStrategy = null;
  275   			if ( accessType != null && settings.isSecondLevelCacheEnabled() ) {
  276   				log.trace( "Building cache for collection data [" + model.getRole() + "]" );
  277   				CollectionRegion collectionRegion = settings.getRegionFactory().buildCollectionRegion( cacheRegionName, properties, CacheDataDescriptionImpl.decode( model ) );
  278   				accessStrategy = collectionRegion.buildAccessStrategy( accessType );
  279   				entityAccessStrategies.put( cacheRegionName, accessStrategy );
  280   				allCacheRegions.put( cacheRegionName, collectionRegion );
  281   			}
  282   			CollectionPersister persister = PersisterFactory.createCollectionPersister( cfg, model, accessStrategy, this) ;
  283   			collectionPersisters.put( model.getRole(), persister.getCollectionMetadata() );
  284   			Type indexType = persister.getIndexType();
  285   			if ( indexType != null && indexType.isAssociationType() && !indexType.isAnyType() ) {
  286   				String entityName = ( ( AssociationType ) indexType ).getAssociatedEntityName( this );
  287   				Set roles = ( Set ) tmpEntityToCollectionRoleMap.get( entityName );
  288   				if ( roles == null ) {
  289   					roles = new HashSet();
  290   					tmpEntityToCollectionRoleMap.put( entityName, roles );
  291   				}
  292   				roles.add( persister.getRole() );
  293   			}
  294   			Type elementType = persister.getElementType();
  295   			if ( elementType.isAssociationType() && !elementType.isAnyType() ) {
  296   				String entityName = ( ( AssociationType ) elementType ).getAssociatedEntityName( this );
  297   				Set roles = ( Set ) tmpEntityToCollectionRoleMap.get( entityName );
  298   				if ( roles == null ) {
  299   					roles = new HashSet();
  300   					tmpEntityToCollectionRoleMap.put( entityName, roles );
  301   				}
  302   				roles.add( persister.getRole() );
  303   			}
  304   		}
  305   		collectionMetadata = Collections.unmodifiableMap(collectionPersisters);
  306   		Iterator itr = tmpEntityToCollectionRoleMap.entrySet().iterator();
  307   		while ( itr.hasNext() ) {
  308   			final Map.Entry entry = ( Map.Entry ) itr.next();
  309   			entry.setValue( Collections.unmodifiableSet( ( Set ) entry.getValue() ) );
  310   		}
  311   		collectionRolesByEntityParticipant = Collections.unmodifiableMap( tmpEntityToCollectionRoleMap );
  312   
  313   		//Named Queries:
  314   		namedQueries = new HashMap( cfg.getNamedQueries() );
  315   		namedSqlQueries = new HashMap( cfg.getNamedSQLQueries() );
  316   		sqlResultSetMappings = new HashMap( cfg.getSqlResultSetMappings() );
  317   		imports = new HashMap( cfg.getImports() );
  318   
  319   		// after *all* persisters and named queries are registered
  320   		Iterator iter = entityPersisters.values().iterator();
  321   		while ( iter.hasNext() ) {
  322   			( (EntityPersister) iter.next() ).postInstantiate();
  323   		}
  324   		iter = collectionPersisters.values().iterator();
  325   		while ( iter.hasNext() ) {
  326   			( (CollectionPersister) iter.next() ).postInstantiate();
  327   		}
  328   
  329   		//JNDI + Serialization:
  330   
  331   		name = settings.getSessionFactoryName();
  332   		try {
  333   			uuid = (String) UUID_GENERATOR.generate(null, null);
  334   		}
  335   		catch (Exception e) {
  336   			throw new AssertionFailure("Could not generate UUID");
  337   		}
  338   		SessionFactoryObjectFactory.addInstance(uuid, name, this, properties);
  339   
  340   		log.debug("instantiated session factory");
  341   
  342   		if ( settings.isAutoCreateSchema() ) {
  343   			new SchemaExport( cfg, settings ).create( false, true );
  344   		}
  345   		if ( settings.isAutoUpdateSchema() ) {
  346   			new SchemaUpdate( cfg, settings ).execute( false, true );
  347   		}
  348   		if ( settings.isAutoValidateSchema() ) {
  349   			new SchemaValidator( cfg, settings ).validate();
  350   		}
  351   		if ( settings.isAutoDropSchema() ) {
  352   			schemaExport = new SchemaExport( cfg, settings );
  353   		}
  354   
  355   		if ( settings.getTransactionManagerLookup()!=null ) {
  356   			log.debug("obtaining JTA TransactionManager");
  357   			transactionManager = settings.getTransactionManagerLookup().getTransactionManager(properties);
  358   		}
  359   		else {
  360   			if ( settings.getTransactionFactory().isTransactionManagerRequired() ) {
  361   				throw new HibernateException("The chosen transaction strategy requires access to the JTA TransactionManager");
  362   			}
  363   			transactionManager = null;
  364   		}
  365   
  366   		currentSessionContext = buildCurrentSessionContext();
  367   
  368   		if ( settings.isQueryCacheEnabled() ) {
  369   			updateTimestampsCache = new UpdateTimestampsCache(settings, properties);
  370   			queryCache = settings.getQueryCacheFactory()
  371   			        .getQueryCache(null, updateTimestampsCache, settings, properties);
  372   			queryCaches = new HashMap();
  373   			allCacheRegions.put( updateTimestampsCache.getRegion().getName(), updateTimestampsCache.getRegion() );
  374   			allCacheRegions.put( queryCache.getRegion().getName(), queryCache.getRegion() );
  375   		}
  376   		else {
  377   			updateTimestampsCache = null;
  378   			queryCache = null;
  379   			queryCaches = null;
  380   		}
  381   
  382   		//checking for named queries
  383   		if ( settings.isNamedQueryStartupCheckingEnabled() ) {
  384   			Map errors = checkNamedQueries();
  385   			if ( !errors.isEmpty() ) {
  386   				Set keys = errors.keySet();
  387   				StringBuffer failingQueries = new StringBuffer( "Errors in named queries: " );
  388   				for ( Iterator iterator = keys.iterator() ; iterator.hasNext() ; ) {
  389   					String queryName = ( String ) iterator.next();
  390   					HibernateException e = ( HibernateException ) errors.get( queryName );
  391   					failingQueries.append( queryName );
  392   					if ( iterator.hasNext() ) {
  393   						failingQueries.append( ", " );
  394   					}
  395   					log.error( "Error in named query: " + queryName, e );
  396   				}
  397   				throw new HibernateException( failingQueries.toString() );
  398   			}
  399   		}
  400   
  401   		//stats
  402   		getStatistics().setStatisticsEnabled( settings.isStatisticsEnabled() );
  403   
  404   		// EntityNotFoundDelegate
  405   		EntityNotFoundDelegate entityNotFoundDelegate = cfg.getEntityNotFoundDelegate();
  406   		if ( entityNotFoundDelegate == null ) {
  407   			entityNotFoundDelegate = new EntityNotFoundDelegate() {
  408   				public void handleEntityNotFound(String entityName, Serializable id) {
  409   					throw new ObjectNotFoundException( id, entityName );
  410   				}
  411   			};
  412   		}
  413   		this.entityNotFoundDelegate = entityNotFoundDelegate;
  414   
  415   		this.observer.sessionFactoryCreated( this );
  416   	}
  417   
  418   	public QueryPlanCache getQueryPlanCache() {
  419   		return queryPlanCache;
  420   	}
  421   
  422   	private Map checkNamedQueries() throws HibernateException {
  423   		Map errors = new HashMap();
  424   
  425   		// Check named HQL queries
  426   		log.debug("Checking " + namedQueries.size() + " named HQL queries");
  427   		Iterator itr = namedQueries.entrySet().iterator();
  428   		while ( itr.hasNext() ) {
  429   			final Map.Entry entry = ( Map.Entry ) itr.next();
  430   			final String queryName = ( String ) entry.getKey();
  431   			final NamedQueryDefinition qd = ( NamedQueryDefinition ) entry.getValue();
  432   			// this will throw an error if there's something wrong.
  433   			try {
  434   				log.debug("Checking named query: " + queryName);
  435   				//TODO: BUG! this currently fails for named queries for non-POJO entities
  436   				queryPlanCache.getHQLQueryPlan( qd.getQueryString(), false, CollectionHelper.EMPTY_MAP );
  437   			}
  438   			catch ( QueryException e ) {
  439   				errors.put( queryName, e );
  440   			}
  441   			catch ( MappingException e ) {
  442   				errors.put( queryName, e );
  443   			}
  444   		}
  445   
  446   		log.debug("Checking " + namedSqlQueries.size() + " named SQL queries");
  447   		itr = namedSqlQueries.entrySet().iterator();
  448   		while ( itr.hasNext() ) {
  449   			final Map.Entry entry = ( Map.Entry ) itr.next();
  450   			final String queryName = ( String ) entry.getKey();
  451   			final NamedSQLQueryDefinition qd = ( NamedSQLQueryDefinition ) entry.getValue();
  452   			// this will throw an error if there's something wrong.
  453   			try {
  454   				log.debug("Checking named SQL query: " + queryName);
  455   				// TODO : would be really nice to cache the spec on the query-def so as to not have to re-calc the hash;
  456   				// currently not doable though because of the resultset-ref stuff...
  457   				NativeSQLQuerySpecification spec;
  458   				if ( qd.getResultSetRef() != null ) {
  459   					ResultSetMappingDefinition definition = ( ResultSetMappingDefinition ) sqlResultSetMappings.get( qd.getResultSetRef() );
  460   					if ( definition == null ) {
  461   						throw new MappingException( "Unable to find resultset-ref definition: " + qd.getResultSetRef() );
  462   					}
  463   					spec = new NativeSQLQuerySpecification(
  464   							qd.getQueryString(),
  465   					        definition.getQueryReturns(),
  466   					        qd.getQuerySpaces()
  467   					);
  468   				}
  469   				else {
  470   					spec =  new NativeSQLQuerySpecification(
  471   							qd.getQueryString(),
  472   					        qd.getQueryReturns(),
  473   					        qd.getQuerySpaces()
  474   					);
  475   				}
  476   				queryPlanCache.getNativeSQLQueryPlan( spec );
  477   			}
  478   			catch ( QueryException e ) {
  479   				errors.put( queryName, e );
  480   			}
  481   			catch ( MappingException e ) {
  482   				errors.put( queryName, e );
  483   			}
  484   		}
  485   
  486   		return errors;
  487   	}
  488   
  489   	public StatelessSession openStatelessSession() {
  490   		return new StatelessSessionImpl( null, this );
  491   	}
  492   
  493   	public StatelessSession openStatelessSession(Connection connection) {
  494   		return new StatelessSessionImpl( connection, this );
  495   	}
  496   
  497   	private SessionImpl openSession(
  498   		Connection connection,
  499   	    boolean autoClose,
  500   	    long timestamp,
  501   	    Interceptor sessionLocalInterceptor
  502   	) {
  503   		return new SessionImpl(
  504   		        connection,
  505   		        this,
  506   		        autoClose,
  507   		        timestamp,
  508   		        sessionLocalInterceptor == null ? interceptor : sessionLocalInterceptor,
  509   		        settings.getDefaultEntityMode(),
  510   		        settings.isFlushBeforeCompletionEnabled(),
  511   		        settings.isAutoCloseSessionEnabled(),
  512   		        settings.getConnectionReleaseMode()
  513   			);
  514   	}
  515   
  516   	public org.hibernate.classic.Session openSession(Connection connection, Interceptor sessionLocalInterceptor) {
  517   		return openSession(connection, false, Long.MIN_VALUE, sessionLocalInterceptor);
  518   	}
  519   
  520   	public org.hibernate.classic.Session openSession(Interceptor sessionLocalInterceptor)
  521   	throws HibernateException {
  522   		// note that this timestamp is not correct if the connection provider
  523   		// returns an older JDBC connection that was associated with a
  524   		// transaction that was already begun before openSession() was called
  525   		// (don't know any possible solution to this!)
  526   		long timestamp = settings.getRegionFactory().nextTimestamp();
  527   		return openSession( null, true, timestamp, sessionLocalInterceptor );
  528   	}
  529   
  530   	public org.hibernate.classic.Session openSession(Connection connection) {
  531   		return openSession(connection, interceptor); //prevents this session from adding things to cache
  532   	}
  533   
  534   	public org.hibernate.classic.Session openSession() throws HibernateException {
  535   		return openSession(interceptor);
  536   	}
  537   
  538   	public org.hibernate.classic.Session openTemporarySession() throws HibernateException {
  539   		return new SessionImpl(
  540   				null,
  541   		        this,
  542   		        true,
  543   		        settings.getRegionFactory().nextTimestamp(),
  544   		        interceptor,
  545   		        settings.getDefaultEntityMode(),
  546   		        false,
  547   		        false,
  548   		        ConnectionReleaseMode.AFTER_STATEMENT
  549   			);
  550   	}
  551   
  552   	public org.hibernate.classic.Session openSession(
  553   			final Connection connection,
  554   	        final boolean flushBeforeCompletionEnabled,
  555   	        final boolean autoCloseSessionEnabled,
  556   	        final ConnectionReleaseMode connectionReleaseMode) throws HibernateException {
  557   		return new SessionImpl(
  558   				connection,
  559   		        this,
  560   		        true,
  561   		        settings.getRegionFactory().nextTimestamp(),
  562   		        interceptor,
  563   		        settings.getDefaultEntityMode(),
  564   		        flushBeforeCompletionEnabled,
  565   		        autoCloseSessionEnabled,
  566   		        connectionReleaseMode
  567   			);
  568   	}
  569   
  570   	public org.hibernate.classic.Session getCurrentSession() throws HibernateException {
  571   		if ( currentSessionContext == null ) {
  572   			throw new HibernateException( "No CurrentSessionContext configured!" );
  573   		}
  574   		return currentSessionContext.currentSession();
  575   	}
  576   
  577   	public EntityPersister getEntityPersister(String entityName) throws MappingException {
  578   		EntityPersister result = (EntityPersister) entityPersisters.get(entityName);
  579   		if (result==null) {
  580   			throw new MappingException( "Unknown entity: " + entityName );
  581   		}
  582   		return result;
  583   	}
  584   
  585   	public CollectionPersister getCollectionPersister(String role) throws MappingException {
  586   		CollectionPersister result = (CollectionPersister) collectionPersisters.get(role);
  587   		if (result==null) {
  588   			throw new MappingException( "Unknown collection role: " + role );
  589   		}
  590   		return result;
  591   	}
  592   
  593   	public Settings getSettings() {
  594   		return settings;
  595   	}
  596   
  597   	public Dialect getDialect() {
  598   		return settings.getDialect();
  599   	}
  600   
  601   	public Interceptor getInterceptor()
  602   	{
  603   		return interceptor;
  604   	}
  605   
  606   	public TransactionFactory getTransactionFactory() {
  607   		return settings.getTransactionFactory();
  608   	}
  609   
  610   	public TransactionManager getTransactionManager() {
  611   		return transactionManager;
  612   	}
  613   
  614   	public SQLExceptionConverter getSQLExceptionConverter() {
  615   		return settings.getSQLExceptionConverter();
  616   	}
  617   
  618   	public Set getCollectionRolesByEntityParticipant(String entityName) {
  619   		return ( Set ) collectionRolesByEntityParticipant.get( entityName );
  620   	}
  621   
  622   	// from javax.naming.Referenceable
  623   	public Reference getReference() throws NamingException {
  624   		log.debug("Returning a Reference to the SessionFactory");
  625   		return new Reference(
  626   			SessionFactoryImpl.class.getName(),
  627   		    new StringRefAddr("uuid", uuid),
  628   		    SessionFactoryObjectFactory.class.getName(),
  629   		    null
  630   		);
  631   	}
  632   
  633   	private Object readResolve() throws ObjectStreamException {
  634   		log.trace("Resolving serialized SessionFactory");
  635   		// look for the instance by uuid
  636   		Object result = SessionFactoryObjectFactory.getInstance(uuid);
  637   		if (result==null) {
  638   			// in case we were deserialized in a different JVM, look for an instance with the same name
  639   			// (alternatively we could do an actual JNDI lookup here....)
  640   			result = SessionFactoryObjectFactory.getNamedInstance(name);
  641   			if (result==null) {
  642   				throw new InvalidObjectException("Could not find a SessionFactory named: " + name);
  643   			}
  644   			else {
  645   				log.debug("resolved SessionFactory by name");
  646   			}
  647   		}
  648   		else {
  649   			log.debug("resolved SessionFactory by uid");
  650   		}
  651   		return result;
  652   	}
  653   
  654   	public NamedQueryDefinition getNamedQuery(String queryName) {
  655   		return (NamedQueryDefinition) namedQueries.get(queryName);
  656   	}
  657   
  658   	public NamedSQLQueryDefinition getNamedSQLQuery(String queryName) {
  659   		return (NamedSQLQueryDefinition) namedSqlQueries.get(queryName);
  660   	}
  661   
  662   	public ResultSetMappingDefinition getResultSetMapping(String resultSetName) {
  663   		return (ResultSetMappingDefinition) sqlResultSetMappings.get(resultSetName);
  664   	}
  665   
  666   	public Type getIdentifierType(String className) throws MappingException {
  667   		return getEntityPersister(className).getIdentifierType();
  668   	}
  669   	public String getIdentifierPropertyName(String className) throws MappingException {
  670   		return getEntityPersister(className).getIdentifierPropertyName();
  671   	}
  672   
  673   	private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
  674   		log.trace("deserializing");
  675   		in.defaultReadObject();
  676   		log.debug("deserialized: " + uuid);
  677   	}
  678   
  679   	private void writeObject(ObjectOutputStream out) throws IOException {
  680   		log.debug("serializing: " + uuid);
  681   		out.defaultWriteObject();
  682   		log.trace("serialized");
  683   	}
  684   
  685   	public Type[] getReturnTypes(String queryString) throws HibernateException {
  686   		return queryPlanCache.getHQLQueryPlan( queryString, false, CollectionHelper.EMPTY_MAP ).getReturnMetadata().getReturnTypes();
  687   	}
  688   
  689   	public String[] getReturnAliases(String queryString) throws HibernateException {
  690   		return queryPlanCache.getHQLQueryPlan( queryString, false, CollectionHelper.EMPTY_MAP ).getReturnMetadata().getReturnAliases();
  691   	}
  692   
  693   	public ClassMetadata getClassMetadata(Class persistentClass) throws HibernateException {
  694   		return getClassMetadata( persistentClass.getName() );
  695   	}
  696   
  697   	public CollectionMetadata getCollectionMetadata(String roleName) throws HibernateException {
  698   		return (CollectionMetadata) collectionMetadata.get(roleName);
  699   	}
  700   
  701   	public ClassMetadata getClassMetadata(String entityName) throws HibernateException {
  702   		return (ClassMetadata) classMetadata.get(entityName);
  703   	}
  704   
  705   	/**
  706   	 * Return the names of all persistent (mapped) classes that extend or implement the
  707   	 * given class or interface, accounting for implicit/explicit polymorphism settings
  708   	 * and excluding mapped subclasses/joined-subclasses of other classes in the result.
  709   	 */
  710   	public String[] getImplementors(String className) throws MappingException {
  711   
  712   		final Class clazz;
  713   		try {
  714   			clazz = ReflectHelper.classForName(className);
  715   		}
  716   		catch (ClassNotFoundException cnfe) {
  717   			return new String[] { className }; //for a dynamic-class
  718   		}
  719   
  720   		ArrayList results = new ArrayList();
  721   		Iterator iter = entityPersisters.values().iterator();
  722   		while ( iter.hasNext() ) {
  723   			//test this entity to see if we must query it
  724   			EntityPersister testPersister = (EntityPersister) iter.next();
  725   			if ( testPersister instanceof Queryable ) {
  726   				Queryable testQueryable = (Queryable) testPersister;
  727   				String testClassName = testQueryable.getEntityName();
  728   				boolean isMappedClass = className.equals(testClassName);
  729   				if ( testQueryable.isExplicitPolymorphism() ) {
  730   					if ( isMappedClass ) {
  731   						return new String[] {className}; //NOTE EARLY EXIT
  732   					}
  733   				}
  734   				else {
  735   					if (isMappedClass) {
  736   						results.add(testClassName);
  737   					}
  738   					else {
  739   						final Class mappedClass = testQueryable.getMappedClass( EntityMode.POJO );
  740   						if ( mappedClass!=null && clazz.isAssignableFrom( mappedClass ) ) {
  741   							final boolean assignableSuperclass;
  742   							if ( testQueryable.isInherited() ) {
  743   								Class mappedSuperclass = getEntityPersister( testQueryable.getMappedSuperclass() ).getMappedClass( EntityMode.POJO);
  744   								assignableSuperclass = clazz.isAssignableFrom(mappedSuperclass);
  745   							}
  746   							else {
  747   								assignableSuperclass = false;
  748   							}
  749   							if ( !assignableSuperclass ) {
  750   								results.add( testClassName );
  751   							}
  752   						}
  753   					}
  754   				}
  755   			}
  756   		}
  757   		return (String[]) results.toArray( new String[ results.size() ] );
  758   	}
  759   
  760   	public String getImportedClassName(String className) {
  761   		String result = (String) imports.get(className);
  762   		if (result==null) {
  763   			try {
  764   				ReflectHelper.classForName(className);
  765   				return className;
  766   			}
  767   			catch (ClassNotFoundException cnfe) {
  768   				return null;
  769   			}
  770   		}
  771   		else {
  772   			return result;
  773   		}
  774   	}
  775   
  776   	public Map getAllClassMetadata() throws HibernateException {
  777   		return classMetadata;
  778   	}
  779   
  780   	public Map getAllCollectionMetadata() throws HibernateException {
  781   		return collectionMetadata;
  782   	}
  783   
  784   	/**
  785   	 * Closes the session factory, releasing all held resources.
  786   	 *
  787   	 * <ol>
  788   	 * <li>cleans up used cache regions and "stops" the cache provider.
  789   	 * <li>close the JDBC connection
  790   	 * <li>remove the JNDI binding
  791   	 * </ol>
  792   	 *
  793   	 * Note: Be aware that the sessionfactory instance still can
  794   	 * be a "heavy" object memory wise after close() has been called.  Thus
  795   	 * it is important to not keep referencing the instance to let the garbage
  796   	 * collector release the memory.
  797   	 */
  798   	public void close() throws HibernateException {
  799   
  800   		if ( isClosed ) {
  801   			log.trace( "already closed" );
  802   			return;
  803   		}
  804   
  805   		log.info("closing");
  806   
  807   		isClosed = true;
  808   
  809   		Iterator iter = entityPersisters.values().iterator();
  810   		while ( iter.hasNext() ) {
  811   			EntityPersister p = (EntityPersister) iter.next();
  812   			if ( p.hasCache() ) {
  813   				p.getCacheAccessStrategy().getRegion().destroy();
  814   			}
  815   		}
  816   
  817   		iter = collectionPersisters.values().iterator();
  818   		while ( iter.hasNext() ) {
  819   			CollectionPersister p = (CollectionPersister) iter.next();
  820   			if ( p.hasCache() ) {
  821   				p.getCacheAccessStrategy().getRegion().destroy();
  822   			}
  823   		}
  824   
  825   		if ( settings.isQueryCacheEnabled() )  {
  826   			queryCache.destroy();
  827   
  828   			iter = queryCaches.values().iterator();
  829   			while ( iter.hasNext() ) {
  830   				QueryCache cache = (QueryCache) iter.next();
  831   				cache.destroy();
  832   			}
  833   			updateTimestampsCache.destroy();
  834   		}
  835   
  836   		settings.getRegionFactory().stop();
  837   
  838   		if ( settings.isAutoDropSchema() ) {
  839   			schemaExport.drop( false, true );
  840   		}
  841   
  842   		try {
  843   			settings.getConnectionProvider().close();
  844   		}
  845   		finally {
  846   			SessionFactoryObjectFactory.removeInstance(uuid, name, properties);
  847   		}
  848   
  849   		observer.sessionFactoryClosed( this );
  850   		eventListeners.destroyListeners();
  851   	}
  852   
  853   	public void evictEntity(String entityName, Serializable id) throws HibernateException {
  854   		EntityPersister p = getEntityPersister( entityName );
  855   		if ( p.hasCache() ) {
  856   			if ( log.isDebugEnabled() ) {
  857   				log.debug( "evicting second-level cache: " + MessageHelper.infoString(p, id, this) );
  858   			}
  859   			CacheKey cacheKey = new CacheKey( id, p.getIdentifierType(), p.getRootEntityName(), EntityMode.POJO, this );
  860   			p.getCacheAccessStrategy().evict( cacheKey );
  861   		}
  862   	}
  863   
  864   	public void evictEntity(String entityName) throws HibernateException {
  865   		EntityPersister p = getEntityPersister( entityName );
  866   		if ( p.hasCache() ) {
  867   			if ( log.isDebugEnabled() ) {
  868   				log.debug( "evicting second-level cache: " + p.getEntityName() );
  869   			}
  870   			p.getCacheAccessStrategy().evictAll();
  871   		}
  872   	}
  873   
  874   	public void evict(Class persistentClass, Serializable id) throws HibernateException {
  875   		EntityPersister p = getEntityPersister( persistentClass.getName() );
  876   		if ( p.hasCache() ) {
  877   			if ( log.isDebugEnabled() ) {
  878   				log.debug( "evicting second-level cache: " + MessageHelper.infoString(p, id, this) );
  879   			}
  880   			CacheKey cacheKey = new CacheKey( id, p.getIdentifierType(), p.getRootEntityName(), EntityMode.POJO, this );
  881   			p.getCacheAccessStrategy().evict( cacheKey );
  882   		}
  883   	}
  884   
  885   	public void evict(Class persistentClass) throws HibernateException {
  886   		EntityPersister p = getEntityPersister( persistentClass.getName() );
  887   		if ( p.hasCache() ) {
  888   			if ( log.isDebugEnabled() ) {
  889   				log.debug( "evicting second-level cache: " + p.getEntityName() );
  890   			}
  891   			p.getCacheAccessStrategy().evictAll();
  892   		}
  893   	}
  894   
  895   	public void evictCollection(String roleName, Serializable id) throws HibernateException {
  896   		CollectionPersister p = getCollectionPersister( roleName );
  897   		if ( p.hasCache() ) {
  898   			if ( log.isDebugEnabled() ) {
  899   				log.debug( "evicting second-level cache: " + MessageHelper.collectionInfoString(p, id, this) );
  900   			}
  901   			CacheKey cacheKey = new CacheKey( id, p.getKeyType(), p.getRole(), EntityMode.POJO, this );
  902   			p.getCacheAccessStrategy().evict( cacheKey );
  903   		}
  904   	}
  905   
  906   	public void evictCollection(String roleName) throws HibernateException {
  907   		CollectionPersister p = getCollectionPersister( roleName );
  908   		if ( p.hasCache() ) {
  909   			if ( log.isDebugEnabled() ) {
  910   				log.debug( "evicting second-level cache: " + p.getRole() );
  911   			}
  912   			p.getCacheAccessStrategy().evictAll();
  913   		}
  914   	}
  915   
  916   	public Type getReferencedPropertyType(String className, String propertyName)
  917   		throws MappingException {
  918   		return getEntityPersister(className).getPropertyType(propertyName);
  919   	}
  920   
  921   	public ConnectionProvider getConnectionProvider() {
  922   		return settings.getConnectionProvider();
  923   	}
  924   
  925   	public UpdateTimestampsCache getUpdateTimestampsCache() {
  926   		return updateTimestampsCache;
  927   	}
  928   
  929   	public QueryCache getQueryCache() {
  930   		return queryCache;
  931   	}
  932   
  933   	public QueryCache getQueryCache(String regionName) throws HibernateException {
  934   		if ( regionName == null ) {
  935   			return getQueryCache();
  936   		}
  937   
  938   		if ( !settings.isQueryCacheEnabled() ) {
  939   			return null;
  940   		}
  941   
  942   		synchronized ( allCacheRegions ) {
  943   			QueryCache currentQueryCache = ( QueryCache ) queryCaches.get( regionName );
  944   			if ( currentQueryCache == null ) {
  945   				currentQueryCache = settings.getQueryCacheFactory().getQueryCache( regionName, updateTimestampsCache, settings, properties );
  946   				queryCaches.put( regionName, currentQueryCache );
  947   				allCacheRegions.put( currentQueryCache.getRegion().getName(), currentQueryCache.getRegion() );
  948   			}
  949   			return currentQueryCache;
  950   		}
  951   	}
  952   
  953   	public Region getSecondLevelCacheRegion(String regionName) {
  954   		synchronized ( allCacheRegions ) {
  955   			return ( Region ) allCacheRegions.get( regionName );
  956   		}
  957   	}
  958   
  959   	public Map getAllSecondLevelCacheRegions() {
  960   		synchronized ( allCacheRegions ) {
  961   			return new HashMap( allCacheRegions );
  962   		}
  963   	}
  964   
  965   	public boolean isClosed() {
  966   		return isClosed;
  967   	}
  968   
  969   	public Statistics getStatistics() {
  970   		return statistics;
  971   	}
  972   
  973   	public StatisticsImplementor getStatisticsImplementor() {
  974   		return statistics;
  975   	}
  976   
  977   	public void evictQueries() throws HibernateException {
  978   		if ( settings.isQueryCacheEnabled() ) {
  979   			queryCache.clear();
  980   		}
  981   	}
  982   
  983   	public void evictQueries(String cacheRegion) throws HibernateException {
  984   		if (cacheRegion==null) {
  985   			throw new NullPointerException("use the zero-argument form to evict the default query cache");
  986   		}
  987   		else {
  988   			synchronized (allCacheRegions) {
  989   				if ( settings.isQueryCacheEnabled() ) {
  990   					QueryCache currentQueryCache = (QueryCache) queryCaches.get(cacheRegion);
  991   					if ( currentQueryCache != null ) {
  992   						currentQueryCache.clear();
  993   					}
  994   				}
  995   			}
  996   		}
  997   	}
  998   
  999   	public FilterDefinition getFilterDefinition(String filterName) throws HibernateException {
 1000   		FilterDefinition def = ( FilterDefinition ) filters.get( filterName );
 1001   		if ( def == null ) {
 1002   			throw new HibernateException( "No such filter configured [" + filterName + "]" );
 1003   		}
 1004   		return def;
 1005   	}
 1006   
 1007   	public Set getDefinedFilterNames() {
 1008   		return filters.keySet();
 1009   	}
 1010   
 1011   	public BatcherFactory getBatcherFactory() {
 1012   		return settings.getBatcherFactory();
 1013   	}
 1014   
 1015   	public IdentifierGenerator getIdentifierGenerator(String rootEntityName) {
 1016   		return (IdentifierGenerator) identifierGenerators.get(rootEntityName);
 1017   	}
 1018   
 1019   	private CurrentSessionContext buildCurrentSessionContext() {
 1020   		String impl = properties.getProperty( Environment.CURRENT_SESSION_CONTEXT_CLASS );
 1021   		// for backward-compatability
 1022   		if ( impl == null && transactionManager != null ) {
 1023   			impl = "jta";
 1024   		}
 1025   
 1026   		if ( impl == null ) {
 1027   			return null;
 1028   		}
 1029   		else if ( "jta".equals( impl ) ) {
 1030   			if ( settings.getTransactionFactory().areCallbacksLocalToHibernateTransactions() ) {
 1031   				log.warn( "JTASessionContext being used with JDBCTransactionFactory; auto-flush will not operate correctly with getCurrentSession()" );
 1032   			}
 1033   			return new JTASessionContext( this );
 1034   		}
 1035   		else if ( "thread".equals( impl ) ) {
 1036   			return new ThreadLocalSessionContext( this );
 1037   		}
 1038   		else if ( "managed".equals( impl ) ) {
 1039   			return new ManagedSessionContext( this );
 1040   		}
 1041   		else {
 1042   			try {
 1043   				Class implClass = ReflectHelper.classForName( impl );
 1044   				return ( CurrentSessionContext ) implClass
 1045   						.getConstructor( new Class[] { SessionFactoryImplementor.class } )
 1046   						.newInstance( new Object[] { this } );
 1047   			}
 1048   			catch( Throwable t ) {
 1049   				log.error( "Unable to construct current session context [" + impl + "]", t );
 1050   				return null;
 1051   			}
 1052   		}
 1053   	}
 1054   
 1055   	public EventListeners getEventListeners()
 1056   	{
 1057   		return eventListeners;
 1058   	}
 1059   
 1060   	public EntityNotFoundDelegate getEntityNotFoundDelegate() {
 1061   		return entityNotFoundDelegate;
 1062   	}
 1063   
 1064   	/**
 1065   	 * Custom serialization hook used during Session serialization.
 1066   	 *
 1067   	 * @param oos The stream to which to write the factory
 1068   	 * @throws IOException Indicates problems writing out the serial data stream
 1069   	 */
 1070   	void serialize(ObjectOutputStream oos) throws IOException {
 1071   		oos.writeUTF( uuid );
 1072   		oos.writeBoolean( name != null );
 1073   		if ( name != null ) {
 1074   			oos.writeUTF( name );
 1075   		}
 1076   	}
 1077   
 1078   	/**
 1079   	 * Custom deserialization hook used during Session deserialization.
 1080   	 *
 1081   	 * @param ois The stream from which to "read" the factory
 1082   	 * @return The deserialized factory
 1083   	 * @throws IOException indicates problems reading back serial data stream
 1084   	 * @throws ClassNotFoundException indicates problems reading back serial data stream
 1085   	 */
 1086   	static SessionFactoryImpl deserialize(ObjectInputStream ois) throws IOException, ClassNotFoundException {
 1087   		String uuid = ois.readUTF();
 1088   		boolean isNamed = ois.readBoolean();
 1089   		String name = null;
 1090   		if ( isNamed ) {
 1091   			name = ois.readUTF();
 1092   		}
 1093   		Object result = SessionFactoryObjectFactory.getInstance( uuid );
 1094   		if ( result == null ) {
 1095   			log.trace( "could not locate session factory by uuid [" + uuid + "] during session deserialization; trying name" );
 1096   			if ( isNamed ) {
 1097   				result = SessionFactoryObjectFactory.getNamedInstance( name );
 1098   			}
 1099   			if ( result == null ) {
 1100   				throw new InvalidObjectException( "could not resolve session factory during session deserialization [uuid=" + uuid + ", name=" + name + "]" );
 1101   			}
 1102   		}
 1103   		return ( SessionFactoryImpl ) result;
 1104   	}
 1105   
 1106   	public SQLFunctionRegistry getSqlFunctionRegistry() {
 1107   		return sqlFunctionRegistry;
 1108   	}
 1109   }

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