接学习四,下来就是调用configuration的buildSessionFactory方法来创建一个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 ); }