/** * Closes the session factory, releasing all held resources. * * <ol> * <li>cleans up used cache regions and "stops" the cache provider. * <li>close the JDBC connection * <li>remove the JNDI binding * </ol> * * Note: Be aware that the sessionfactory instance still can be a "heavy" object memory wise after * close() has been called. Thus it is important to not keep referencing the instance to let the * garbage collector release the memory. */ public void close() throws HibernateException { if (isClosed) { log.trace("already closed"); return; } log.info("closing"); isClosed = true; Iterator iter = entityPersisters.values().iterator(); while (iter.hasNext()) { EntityPersister p = (EntityPersister) iter.next(); if (p.hasCache()) { p.getCacheAccessStrategy().getRegion().destroy(); } } iter = collectionPersisters.values().iterator(); while (iter.hasNext()) { CollectionPersister p = (CollectionPersister) iter.next(); if (p.hasCache()) { p.getCacheAccessStrategy().getRegion().destroy(); } } if (settings.isQueryCacheEnabled()) { queryCache.destroy(); iter = queryCaches.values().iterator(); while (iter.hasNext()) { QueryCache cache = (QueryCache) iter.next(); cache.destroy(); } updateTimestampsCache.destroy(); } settings.getRegionFactory().stop(); if (settings.isAutoDropSchema()) { schemaExport.drop(false, true); } try { settings.getConnectionProvider().close(); } finally { SessionFactoryObjectFactory.removeInstance(uuid, name, properties); } observer.sessionFactoryClosed(this); eventListeners.destroyListeners(); }
public SessionFactoryImpl( Configuration cfg, Mapping mapping, Settings settings, EventListeners listeners, SessionFactoryObserver observer) throws HibernateException { log.info("building session factory"); Statistics concurrentStatistics = null; try { Class concurrentStatsClass = ReflectHelper.classForName("org.hibernate.stat.ConcurrentStatisticsImpl"); Constructor constructor = concurrentStatsClass.getConstructor(new Class[] {SessionFactoryImplementor.class}); concurrentStatistics = (Statistics) constructor.newInstance(new Object[] {this}); log.trace("JDK 1.5 concurrent classes present"); } catch (NoClassDefFoundError noJava5) { log.trace("JDK 1.5 concurrent classes missing"); } catch (Exception noJava5) { log.trace("JDK 1.5 concurrent classes missing"); } if (concurrentStatistics != null) { this.statistics = concurrentStatistics; } else { this.statistics = new StatisticsImpl(this); } if (log.isTraceEnabled()) { log.trace("Statistics initialized with " + statistics.getClass().getName()); } this.properties = new Properties(); this.properties.putAll(cfg.getProperties()); this.interceptor = cfg.getInterceptor(); this.settings = settings; this.sqlFunctionRegistry = new SQLFunctionRegistry(settings.getDialect(), cfg.getSqlFunctions()); this.eventListeners = listeners; this.observer = observer != null ? observer : new SessionFactoryObserver() { public void sessionFactoryCreated(SessionFactory factory) {} public void sessionFactoryClosed(SessionFactory factory) {} }; this.filters = new HashMap(); this.filters.putAll(cfg.getFilterDefinitions()); if (log.isDebugEnabled()) { log.debug("Session factory constructed with filter configurations : " + filters); } if (log.isDebugEnabled()) { log.debug("instantiating session factory with properties: " + properties); } // Caches settings.getRegionFactory().start(settings, properties); // Generators: identifierGenerators = new HashMap(); Iterator classes = cfg.getClassMappings(); while (classes.hasNext()) { PersistentClass model = (PersistentClass) classes.next(); if (!model.isInherited()) { IdentifierGenerator generator = model .getIdentifier() .createIdentifierGenerator( cfg.getIdentifierGeneratorFactory(), settings.getDialect(), settings.getDefaultCatalogName(), settings.getDefaultSchemaName(), (RootClass) model); identifierGenerators.put(model.getEntityName(), generator); } } /////////////////////////////////////////////////////////////////////// // Prepare persisters and link them up with their cache // region/access-strategy final String cacheRegionPrefix = settings.getCacheRegionPrefix() == null ? "" : settings.getCacheRegionPrefix() + "."; entityPersisters = new HashMap(); Map entityAccessStrategies = new HashMap(); Map classMeta = new HashMap(); classes = cfg.getClassMappings(); while (classes.hasNext()) { final PersistentClass model = (PersistentClass) classes.next(); model.prepareTemporaryTables(mapping, settings.getDialect()); final String cacheRegionName = cacheRegionPrefix + model.getRootClass().getCacheRegionName(); // cache region is defined by the root-class in the hierarchy... EntityRegionAccessStrategy accessStrategy = (EntityRegionAccessStrategy) entityAccessStrategies.get(cacheRegionName); if (accessStrategy == null && settings.isSecondLevelCacheEnabled()) { final AccessType accessType = AccessType.parse(model.getCacheConcurrencyStrategy()); if (accessType != null) { log.trace("Building cache for entity data [" + model.getEntityName() + "]"); EntityRegion entityRegion = settings .getRegionFactory() .buildEntityRegion( cacheRegionName, properties, CacheDataDescriptionImpl.decode(model)); accessStrategy = entityRegion.buildAccessStrategy(accessType); entityAccessStrategies.put(cacheRegionName, accessStrategy); allCacheRegions.put(cacheRegionName, entityRegion); } } EntityPersister cp = PersisterFactory.createClassPersister(model, accessStrategy, this, mapping); entityPersisters.put(model.getEntityName(), cp); classMeta.put(model.getEntityName(), cp.getClassMetadata()); } classMetadata = Collections.unmodifiableMap(classMeta); Map tmpEntityToCollectionRoleMap = new HashMap(); collectionPersisters = new HashMap(); Iterator collections = cfg.getCollectionMappings(); while (collections.hasNext()) { Collection model = (Collection) collections.next(); final String cacheRegionName = cacheRegionPrefix + model.getCacheRegionName(); final AccessType accessType = AccessType.parse(model.getCacheConcurrencyStrategy()); CollectionRegionAccessStrategy accessStrategy = null; if (accessType != null && settings.isSecondLevelCacheEnabled()) { log.trace("Building cache for collection data [" + model.getRole() + "]"); CollectionRegion collectionRegion = settings .getRegionFactory() .buildCollectionRegion( cacheRegionName, properties, CacheDataDescriptionImpl.decode(model)); accessStrategy = collectionRegion.buildAccessStrategy(accessType); entityAccessStrategies.put(cacheRegionName, accessStrategy); allCacheRegions.put(cacheRegionName, collectionRegion); } CollectionPersister persister = PersisterFactory.createCollectionPersister(cfg, model, accessStrategy, this); collectionPersisters.put(model.getRole(), persister.getCollectionMetadata()); Type indexType = persister.getIndexType(); if (indexType != null && indexType.isAssociationType() && !indexType.isAnyType()) { String entityName = ((AssociationType) indexType).getAssociatedEntityName(this); Set roles = (Set) tmpEntityToCollectionRoleMap.get(entityName); if (roles == null) { roles = new HashSet(); tmpEntityToCollectionRoleMap.put(entityName, roles); } roles.add(persister.getRole()); } Type elementType = persister.getElementType(); if (elementType.isAssociationType() && !elementType.isAnyType()) { String entityName = ((AssociationType) elementType).getAssociatedEntityName(this); Set roles = (Set) tmpEntityToCollectionRoleMap.get(entityName); if (roles == null) { roles = new HashSet(); tmpEntityToCollectionRoleMap.put(entityName, roles); } roles.add(persister.getRole()); } } collectionMetadata = Collections.unmodifiableMap(collectionPersisters); Iterator itr = tmpEntityToCollectionRoleMap.entrySet().iterator(); while (itr.hasNext()) { final Map.Entry entry = (Map.Entry) itr.next(); entry.setValue(Collections.unmodifiableSet((Set) entry.getValue())); } collectionRolesByEntityParticipant = Collections.unmodifiableMap(tmpEntityToCollectionRoleMap); // Named Queries: namedQueries = new HashMap(cfg.getNamedQueries()); namedSqlQueries = new HashMap(cfg.getNamedSQLQueries()); sqlResultSetMappings = new HashMap(cfg.getSqlResultSetMappings()); imports = new HashMap(cfg.getImports()); // after *all* persisters and named queries are registered Iterator iter = entityPersisters.values().iterator(); while (iter.hasNext()) { final EntityPersister persister = ((EntityPersister) iter.next()); persister.postInstantiate(); registerEntityNameResolvers(persister); } iter = collectionPersisters.values().iterator(); while (iter.hasNext()) { final CollectionPersister persister = ((CollectionPersister) iter.next()); persister.postInstantiate(); } // JNDI + Serialization: name = settings.getSessionFactoryName(); try { uuid = (String) UUID_GENERATOR.generate(null, null); } catch (Exception e) { throw new AssertionFailure("Could not generate UUID"); } SessionFactoryObjectFactory.addInstance(uuid, name, this, properties); log.debug("instantiated session factory"); if (settings.isAutoCreateSchema()) { new SchemaExport(cfg, settings).create(false, true); } if (settings.isAutoUpdateSchema()) { new SchemaUpdate(cfg, settings).execute(false, true); } if (settings.isAutoValidateSchema()) { new SchemaValidator(cfg, settings).validate(); } if (settings.isAutoDropSchema()) { schemaExport = new SchemaExport(cfg, settings); } if (settings.getTransactionManagerLookup() != null) { log.debug("obtaining JTA TransactionManager"); transactionManager = settings.getTransactionManagerLookup().getTransactionManager(properties); } else { if (settings.getTransactionFactory().isTransactionManagerRequired()) { throw new HibernateException( "The chosen transaction strategy requires access to the JTA TransactionManager"); } transactionManager = null; } currentSessionContext = buildCurrentSessionContext(); if (settings.isQueryCacheEnabled()) { updateTimestampsCache = new UpdateTimestampsCache(settings, properties); queryCache = settings .getQueryCacheFactory() .getQueryCache(null, updateTimestampsCache, settings, properties); queryCaches = new HashMap(); allCacheRegions.put( updateTimestampsCache.getRegion().getName(), updateTimestampsCache.getRegion()); allCacheRegions.put(queryCache.getRegion().getName(), queryCache.getRegion()); } else { updateTimestampsCache = null; queryCache = null; queryCaches = null; } // checking for named queries if (settings.isNamedQueryStartupCheckingEnabled()) { Map errors = checkNamedQueries(); if (!errors.isEmpty()) { Set keys = errors.keySet(); StringBuffer failingQueries = new StringBuffer("Errors in named queries: "); for (Iterator iterator = keys.iterator(); iterator.hasNext(); ) { String queryName = (String) iterator.next(); HibernateException e = (HibernateException) errors.get(queryName); failingQueries.append(queryName); if (iterator.hasNext()) { failingQueries.append(", "); } log.error("Error in named query: " + queryName, e); } throw new HibernateException(failingQueries.toString()); } } // stats getStatistics().setStatisticsEnabled(settings.isStatisticsEnabled()); // EntityNotFoundDelegate EntityNotFoundDelegate entityNotFoundDelegate = cfg.getEntityNotFoundDelegate(); if (entityNotFoundDelegate == null) { entityNotFoundDelegate = new EntityNotFoundDelegate() { public void handleEntityNotFound(String entityName, Serializable id) { throw new ObjectNotFoundException(id, entityName); } public boolean isEntityNotFoundException(RuntimeException exception) { return ObjectNotFoundException.class.isInstance(exception); } }; } this.entityNotFoundDelegate = entityNotFoundDelegate; // this needs to happen after persisters are all ready to go... this.fetchProfiles = new HashMap(); itr = cfg.iterateFetchProfiles(); while (itr.hasNext()) { final org.hibernate.mapping.FetchProfile mappingProfile = (org.hibernate.mapping.FetchProfile) itr.next(); final FetchProfile fetchProfile = new FetchProfile(mappingProfile.getName()); Iterator fetches = mappingProfile.getFetches().iterator(); while (fetches.hasNext()) { final org.hibernate.mapping.FetchProfile.Fetch mappingFetch = (org.hibernate.mapping.FetchProfile.Fetch) fetches.next(); // resolve the persister owning the fetch final String entityName = getImportedClassName(mappingFetch.getEntity()); final EntityPersister owner = (EntityPersister) (entityName == null ? null : entityPersisters.get(entityName)); if (owner == null) { throw new HibernateException( "Unable to resolve entity reference [" + mappingFetch.getEntity() + "] in fetch profile [" + fetchProfile.getName() + "]"); } // validate the specified association fetch Type associationType = owner.getPropertyType(mappingFetch.getAssociation()); if (associationType == null || !associationType.isAssociationType()) { throw new HibernateException( "Fetch profile [" + fetchProfile.getName() + "] specified an invalid association"); } // resolve the style final Fetch.Style fetchStyle = Fetch.Style.parse(mappingFetch.getStyle()); // then construct the fetch instance... fetchProfile.addFetch(new Association(owner, mappingFetch.getAssociation()), fetchStyle); ((Loadable) owner).registerAffectingFetchProfile(fetchProfile.getName()); } fetchProfiles.put(fetchProfile.getName(), fetchProfile); } this.observer.sessionFactoryCreated(this); }