当前位置:首页 > 开发 > 编程语言 > Hibernate > 正文

Hibernate源码学习五_创建SessionFactory

发表于: 2013-09-12   作者:bsr1983   来源:转载   浏览次数:
摘要: 接学习四,下来就是调用configuration的buildSessionFactory方法来创建一个sessionFactory了,具体代码如下: public SessionFactory buildSessionFactory(ServiceRegistry serviceRegistry) throws HibernateException { LOG.debugf( "

接学习四,下来就是调用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 );
	}

 

 

 

Hibernate源码学习五_创建SessionFactory

  • 0

    开心

    开心

  • 0

    板砖

    板砖

  • 0

    感动

    感动

  • 0

    有用

    有用

  • 0

    疑问

    疑问

  • 0

    难过

    难过

  • 0

    无聊

    无聊

  • 0

    震惊

    震惊

编辑推荐
Hibernate3源码分析之hibernate.cfg.xml配置文件与SessionFactory类 Hibernate版本(hibernate-distr
  接着上一篇的说hibernate关联映射关系中的一对多单向的,一对多怎么说呢?很多很多的这样的例子
紧接着上一篇,我们来看看另一个序列化类 JavaSerializer(参考源码版本3.0.13)。 这个类一般是用来
缓存不算是ibatis框架的一个亮点,但理解ibatis的缓存设计和实现对我们合理使用ibatis缓存是很有帮
缓存不算是ibatis框架的一个亮点,但理解ibatis的缓存设计和实现对我们合理使用ibatis缓存是很有帮
总结: sessionfactory添加过程中,肯定要寻找hibernate.cfg.xml的配置; hibernate.cfg.xml再去寻
接学习三中的内容,首先看一下如何根据配置文件创建一个SessionFactory,通过跟踪相关代码来了解其
接学习三中的内容,首先看一下如何根据配置文件创建一个SessionFactory,通过跟踪相关代码来了解其
接学习三中的内容,首先看一下如何根据配置文件创建一个SessionFactory,通过跟踪相关代码来了解其
接学习三中的内容,首先看一下如何根据配置文件创建一个SessionFactory,通过跟踪相关代码来了解其
版权所有 IT知识库 CopyRight © 2009-2015 IT知识库 IT610.com , All Rights Reserved. 京ICP备09083238号