Hibernate原始碼學習五_建立SessionFactory

bsr1983發表於2013-09-12

接學習四,下來就是呼叫configurationbuildSessionFactory方法來建立一個sessionFactory了,具體程式碼如下:

public SessionFactory buildSessionFactory(ServiceRegistry serviceRegistry) throws HibernateException {
		LOG.debugf( "Preparing to build session factory with filters : %s", filterDefinitions );
		//註冊型別,包含資料庫方言
		buildTypeRegistrations( serviceRegistry );
		//二次傳遞編譯,包含註解處理
		secondPassCompile();
		if ( !metadataSourceQueue.isEmpty() ) {
			LOG.incompleteMappingMetadataCacheProcessing();
		}
		//校驗所配置的對映類與hbm配置檔案中的屬性是否一致
		validate();
       //校驗全域性配置屬性
		Environment.verifyProperties( properties );
		Properties copy = new Properties();
		copy.putAll( properties );
		//拷貝一份配置,處理佔位符
		ConfigurationHelper.resolvePlaceHolders( copy );
		//通過配置的屬性和註冊的服務建立一個設定
		Settings settings = buildSettings( copy, serviceRegistry );
		//通過註冊的服務,對映檔案,設定,以及一個session工廠的觀察者//(用於監視會話工廠狀態)來建立一個會話工廠的實現
		return new SessionFactoryImpl(
				this,
				mapping,
				serviceRegistry,
				settings,
				sessionFactoryObserver
			);
	}

 下面看一下上述的secondPassCompile()二次傳遞編譯方法secondPassCompile()的具體程式碼:

protected void secondPassCompile () throws MappingException {
		LOG.trace( "Starting secondPassCompile() processing" );
		
		// TEMPORARY
		// Ensure the correct ClassLoader is used in commons-annotations.
//獲取當前執行緒中所使用的classLoader,便於處理結束後,將該classloader在設定為當//前執行緒所使用的類載入器,僅用於保留物件
		ClassLoader tccl = Thread.currentThread().getContextClassLoader();
	//獲取ClassLoaderHelper中的上下文類載入器並設定到當前執行緒,確保所使用的類//載入器,檢視實際程式碼,發現其實返回的還是當前執行緒所使用的上下文載入器,但//ClassLoaderHelper註釋中說明該屬性可以通過客戶自定義注入來進行替換,而且在//Hibernate5中將被替換為其他方式,具體參見ClassLoaderHelper原始碼	Thread.currentThread().setContextClassLoader( ClassLoaderHelper.getContextClassLoader() );

		//process default values first,第一次處理的時候需要設定一下預設值
		{
			if ( !isDefaultProcessed ) {
				//use global delimiters if orm.xml declare it
				Map defaults = reflectionManager.getDefaults();
				final Object isDelimited = defaults.get( "delimited-identifier" );
				if ( isDelimited != null && isDelimited == Boolean.TRUE ) {
					getProperties().put( Environment.GLOBALLY_QUOTED_IDENTIFIERS, "true" );
				}
				// Set default schema name if orm.xml declares it.
				final String schema = (String) defaults.get( "schema" );
				if ( StringHelper.isNotEmpty( schema ) ) {
					getProperties().put( Environment.DEFAULT_SCHEMA, schema );
				}
				// Set default catalog name if orm.xml declares it.
				final String catalog = (String) defaults.get( "catalog" );
				if ( StringHelper.isNotEmpty( catalog ) ) {
					getProperties().put( Environment.DEFAULT_CATALOG, catalog );
				}
				//註解繫結
				AnnotationBinder.bindDefaults( createMappings() );
				isDefaultProcessed = true;
			}
		}

		// process metadata queue
		{
			metadataSourceQueue.syncAnnotatedClasses();
			metadataSourceQueue.processMetadata( determineMetadataSourcePrecedence() );
		}



		try {
			inSecondPass = true;
			processSecondPassesOfType( PkDrivenByDefaultMapsIdSecondPass.class );
			processSecondPassesOfType( SetSimpleValueTypeSecondPass.class );
			processSecondPassesOfType( CopyIdentifierComponentSecondPass.class );
			processFkSecondPassInOrder();
			processSecondPassesOfType( CreateKeySecondPass.class );
			processSecondPassesOfType( SecondaryTableSecondPass.class );

			originalSecondPassCompile();

			inSecondPass = false;
		}
		catch ( RecoverableException e ) {
			//the exception was not recoverable after all
			throw ( RuntimeException ) e.getCause();
		}

		// process cache queue,快取佇列處理
		{
			for ( CacheHolder holder : caches ) {
				if ( holder.isClass ) {
					applyCacheConcurrencyStrategy( holder );
				}
				else {
					applyCollectionCacheConcurrencyStrategy( holder );
				}
			}
			caches.clear();
		}
		//唯一約束處理
		for ( Map.Entry<Table, List<UniqueConstraintHolder>> tableListEntry : uniqueConstraintHoldersByTable.entrySet() ) {
			final Table table = tableListEntry.getKey();
			final List<UniqueConstraintHolder> uniqueConstraints = tableListEntry.getValue();
			for ( UniqueConstraintHolder holder : uniqueConstraints ) {
				buildUniqueKeyFromColumnNames( table, holder.getName(), holder.getColumns() );
			}
		}
		//恢復當前執行緒的上下文類載入器為初始上下文類載入器
		Thread.currentThread().setContextClassLoader( tccl );
	}

 建立sessionFactory所使用的建構函式程式碼:

public SessionFactoryImpl(
			final Configuration cfg,
			Mapping mapping,
			ServiceRegistry serviceRegistry,
			Settings settings,
			SessionFactoryObserver observer) throws HibernateException {
			LOG.debug( "Building session factory" );
//session工廠的設定項
		sessionFactoryOptions = new SessionFactoryOptions() {
			private EntityNotFoundDelegate entityNotFoundDelegate;

			@Override
			public Interceptor getInterceptor() {
				return cfg.getInterceptor();
			}

			@Override
			public EntityNotFoundDelegate getEntityNotFoundDelegate() {
				if ( entityNotFoundDelegate == null ) {
					if ( cfg.getEntityNotFoundDelegate() != null ) {
						entityNotFoundDelegate = cfg.getEntityNotFoundDelegate();
					}
					else {
						entityNotFoundDelegate = new EntityNotFoundDelegate() {
							public void handleEntityNotFound(String entityName, Serializable id) {
								throw new ObjectNotFoundException( id, entityName );
							}
						};
					}
				}
				return entityNotFoundDelegate;
			}
		};

		this.settings = settings;

		this.properties = new Properties();
		this.properties.putAll( cfg.getProperties() );

		this.serviceRegistry = serviceRegistry.getService( SessionFactoryServiceRegistryFactory.class ).buildServiceRegistry(
				this,
				cfg
		);
        //jdbc服務
this.jdbcServices = this.serviceRegistry.getService( JdbcServices.class );
//方言
        this.dialect = this.jdbcServices.getDialect();
//快取訪問服務
		this.cacheAccess = this.serviceRegistry.getService( CacheImplementor.class );
		final RegionFactory regionFactory = cacheAccess.getRegionFactory();
//sql函式註冊,將配置中的自定義方法及制定資料庫方言中的方法註冊到一個//以方法名稱為key,對應的方言所對英的SQLFunction介面實現類的 Map中,
		this.sqlFunctionRegistry = new SQLFunctionRegistry( getDialect(), cfg.getSqlFunctions() );
//如果指定的觀察者不為空,將其新增到當前的觀察者鏈中//SessionFactoryObserverChain
		if ( observer != null ) {
			this.observer.addObserver( observer );
		}

		this.typeResolver = cfg.getTypeResolver().scope( this );
		this.typeHelper = new TypeLocatorImpl( typeResolver );
//過濾器
		this.filters = new HashMap<String, FilterDefinition>();
		this.filters.putAll( cfg.getFilterDefinitions() );

		LOG.debugf( "Session factory constructed with filter configurations : %s", filters );
		LOG.debugf( "Instantiating session factory with properties: %s", properties );

//查詢計劃快取
		this.queryPlanCache = new QueryPlanCache( this );

		// todo : everything above here consider implementing as standard SF service.  specifically: stats, caches, types, function-reg
//內部類,用於定義一個攔截器的SessionFactory觀察者
//攔截器介面可以用於在對持久類進行載入、編輯、更新等操作前進行處理,可//以用於記錄操作資訊
		class IntegratorObserver implements SessionFactoryObserver {
			private ArrayList<Integrator> integrators = new ArrayList<Integrator>();

			@Override
			public void sessionFactoryCreated(SessionFactory factory) {
			}

			@Override
//sessionFactory關閉時,呼叫每個攔截器的回撥方法disintegrate
			public void sessionFactoryClosed(SessionFactory factory) {
				for ( Integrator integrator : integrators ) {
					integrator.disintegrate( SessionFactoryImpl.this, SessionFactoryImpl.this.serviceRegistry );
				}
			}
		}
//攔截器觀察著
		final IntegratorObserver integratorObserver = new IntegratorObserver();
//將攔截器的觀察者加入當前的觀察者鏈中
		this.observer.addObserver( integratorObserver );
//獲取攔截器對應的服務類,設定攔截
		for ( Integrator integrator : serviceRegistry.getService( IntegratorService.class ).getIntegrators() ) {
			integrator.integrate( cfg, this, this.serviceRegistry );
			integratorObserver.integrators.add( integrator );
		}

		//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(),
						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() + ".";
//持久化工廠服務
		final PersisterFactory persisterFactory = serviceRegistry.getService( PersisterFactory.class );
//持久類
		entityPersisters = new HashMap();
		Map entityAccessStrategies = new HashMap();
		Map<String,ClassMetadata> classMeta = new HashMap<String,ClassMetadata>();
//獲取所有對映類
		classes = cfg.getClassMappings();
		while ( classes.hasNext() ) {
			final PersistentClass model = (PersistentClass) classes.next();
			model.prepareTemporaryTables( mapping, 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.fromExternalName( model.getCacheConcurrencyStrategy() );
				if ( accessType != null ) {
					LOG.tracef( "Building shared cache region for entity data [%s]", model.getEntityName() );
					EntityRegion entityRegion = regionFactory.buildEntityRegion( cacheRegionName, properties, CacheDataDescriptionImpl.decode( model ) );
					accessStrategy = entityRegion.buildAccessStrategy( accessType );
					entityAccessStrategies.put( cacheRegionName, accessStrategy );
					cacheAccess.addCacheRegion( cacheRegionName, entityRegion );
				}
			}
			
			NaturalIdRegionAccessStrategy naturalIdAccessStrategy = null;
			if ( model.hasNaturalId() && model.getNaturalIdCacheRegionName() != null ) {
				final String naturalIdCacheRegionName = cacheRegionPrefix + model.getNaturalIdCacheRegionName();
				naturalIdAccessStrategy = ( NaturalIdRegionAccessStrategy ) entityAccessStrategies.get( naturalIdCacheRegionName );
				
				if ( naturalIdAccessStrategy == null && settings.isSecondLevelCacheEnabled() ) {
					final CacheDataDescriptionImpl cacheDataDescription = CacheDataDescriptionImpl.decode( model );
					
					NaturalIdRegion naturalIdRegion = null;
					try {
						naturalIdRegion = regionFactory.buildNaturalIdRegion( naturalIdCacheRegionName, properties,
								cacheDataDescription );
					}
					catch ( UnsupportedOperationException e ) {
						LOG.warnf(
								"Shared cache region factory [%s] does not support natural id caching; " +
										"shared NaturalId caching will be disabled for not be enabled for %s",
								regionFactory.getClass().getName(),
								model.getEntityName()
						);
					}
					
					if (naturalIdRegion != null) {
						naturalIdAccessStrategy = naturalIdRegion.buildAccessStrategy( regionFactory.getDefaultAccessType() );
						entityAccessStrategies.put( naturalIdCacheRegionName, naturalIdAccessStrategy );
						cacheAccess.addCacheRegion(  naturalIdCacheRegionName, naturalIdRegion );
					}
				}
			}
			//根據上述配置生成一個實體對映
			EntityPersister cp = persisterFactory.createEntityPersister(
					model,
					accessStrategy,
					naturalIdAccessStrategy,
					this,
					mapping
			);
	//以實體對映的名稱為key,將對應的持久類加入entityPersisters
			entityPersisters.put( model.getEntityName(), cp );
			classMeta.put( model.getEntityName(), cp.getClassMetadata() );
		}
		this.classMetadata = Collections.unmodifiableMap(classMeta);

		Map<String,Set<String>> tmpEntityToCollectionRoleMap = new HashMap<String,Set<String>>();
		collectionPersisters = new HashMap<String,CollectionPersister>();
		Map<String,CollectionMetadata> tmpCollectionMetadata = new HashMap<String,CollectionMetadata>();
		Iterator collections = cfg.getCollectionMappings();
		while ( collections.hasNext() ) {
			Collection model = (Collection) collections.next();
			final String cacheRegionName = cacheRegionPrefix + model.getCacheRegionName();
			final AccessType accessType = AccessType.fromExternalName( model.getCacheConcurrencyStrategy() );
			CollectionRegionAccessStrategy accessStrategy = null;
			if ( accessType != null && settings.isSecondLevelCacheEnabled() ) {
				LOG.tracev( "Building shared cache region for collection data [{0}]", model.getRole() );
				CollectionRegion collectionRegion = regionFactory.buildCollectionRegion( cacheRegionName, properties, CacheDataDescriptionImpl
						.decode( model ) );
				accessStrategy = collectionRegion.buildAccessStrategy( accessType );
				entityAccessStrategies.put( cacheRegionName, accessStrategy );
				cacheAccess.addCacheRegion( cacheRegionName, collectionRegion );
			}
			CollectionPersister persister = persisterFactory.createCollectionPersister(
					cfg,
					model,
					accessStrategy,
					this
			) ;
			collectionPersisters.put( model.getRole(), persister );
			tmpCollectionMetadata.put( model.getRole(), persister.getCollectionMetadata() );
			Type indexType = persister.getIndexType();
			if ( indexType != null && indexType.isAssociationType() && !indexType.isAnyType() ) {
				String entityName = ( ( AssociationType ) indexType ).getAssociatedEntityName( this );
				Set roles = 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 = tmpEntityToCollectionRoleMap.get( entityName );
				if ( roles == null ) {
					roles = new HashSet();
					tmpEntityToCollectionRoleMap.put( entityName, roles );
				}
				roles.add( persister.getRole() );
			}
		}
		collectionMetadata = Collections.unmodifiableMap( tmpCollectionMetadata );
		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<String, NamedQueryDefinition>( cfg.getNamedQueries() );
		namedSqlQueries = new HashMap<String, NamedSQLQueryDefinition>( cfg.getNamedSQLQueries() );
		sqlResultSetMappings = new HashMap<String, ResultSetMappingDefinition>( cfg.getSqlResultSetMappings() );
		imports = new HashMap<String,String>( 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();
//獲取uuid
		try {
			uuid = (String) UUID_GENERATOR.generate(null, null);
		}
		catch (Exception e) {
			throw new AssertionFailure("Could not generate UUID");
		}
	//將當前的會話工廠加入會話工廠註冊
		SessionFactoryRegistry.INSTANCE.addSessionFactory(
				uuid,
				name,
				settings.isSessionFactoryNameAlsoJndiName(),
				this,
				serviceRegistry.getService( JndiService.class )
		);

		LOG.debug( "Instantiated session factory" );

		settings.getMultiTableBulkIdStrategy().prepare(
				jdbcServices,
				buildLocalConnectionAccess(),
				cfg.createMappings(),
				cfg.buildMapping(),
				properties
		);


		if ( settings.isAutoCreateSchema() ) {
			new SchemaExport( serviceRegistry, cfg )
					.setImportSqlCommandExtractor( serviceRegistry.getService( ImportSqlCommandExtractor.class ) )
					.create( false, true );
		}
		if ( settings.isAutoUpdateSchema() ) {
			new SchemaUpdate( serviceRegistry, cfg ).execute( false, true );
		}
		if ( settings.isAutoValidateSchema() ) {
			new SchemaValidator( serviceRegistry, cfg ).validate();
		}
		if ( settings.isAutoDropSchema() ) {
			schemaExport = new SchemaExport( serviceRegistry, cfg )
					.setImportSqlCommandExtractor( serviceRegistry.getService( ImportSqlCommandExtractor.class ) );
		}

		currentSessionContext = buildCurrentSessionContext();

		//checking for named queries
		if ( settings.isNamedQueryStartupCheckingEnabled() ) {
			final Map<String,HibernateException> errors = checkNamedQueries();
			if ( ! errors.isEmpty() ) {
				StringBuilder failingQueries = new StringBuilder( "Errors in named queries: " );
				String sep = "";
				for ( Map.Entry<String,HibernateException> entry : errors.entrySet() ) {
					LOG.namedQueryError( entry.getKey(), entry.getValue() );
					failingQueries.append( sep ).append( entry.getKey() );
					sep = ", ";
				}
				throw new HibernateException( failingQueries.toString() );
			}
		}

		// 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() );
			for ( org.hibernate.mapping.FetchProfile.Fetch mappingFetch : mappingProfile.getFetches() ) {
				// resolve the persister owning the fetch
				final String entityName = getImportedClassName( mappingFetch.getEntity() );
				final EntityPersister owner = 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.customEntityDirtinessStrategy = determineCustomEntityDirtinessStrategy();
		this.currentTenantIdentifierResolver = determineCurrentTenantIdentifierResolver( cfg.getCurrentTenantIdentifierResolver() );
		this.transactionEnvironment = new TransactionEnvironmentImpl( this );
		this.observer.sessionFactoryCreated( this );
	}

 

 

 

相關文章