`

Hibernate-04-核心Configuration

 
阅读更多

上一篇:         下一篇:

 

一切从配置开始吧!

对于Hibernate,最重要的配置文件当然是:hibernate.cfg.xml

 

先分析一下这个配置文件吧,hibernate-configuration-3.0.dtd这个不要忘记看了,虽然人家只是格式定制而已,OK!开始Configuration之旅吧。

 

Configuration 继承 Serializable,表示这类是可序列化的。好了,不扯啦。4000多行的代码,如果一行一行的看,人都困了,睡意三二。

 

我决定不从构造函数说起,请原谅我一向的风格。

从使用说起,

Configuration conf=new Configuration();

SessionFactory factory=conf.configure().buildSessionFactory();

 

configure()这个方法就是入口。

方法1

public Configuration configure() throws HibernateException {
  configure( "/hibernate.cfg.xml" );
  return this;
}

 

方法2

 

public Configuration configure(String resource) throws HibernateException {
  log.info( "configuring from resource: " + resource );
  InputStream stream = getConfigurationInputStream( resource );
  return doConfigure( stream, resource );
}

 

方法3 

protected Configuration doConfigure(InputStream stream, String resourceName) throws HibernateException {
  try {
   List errors = new ArrayList();
   Document document = xmlHelper.createSAXReader( resourceName, errors, entityResolver )
     .read( new InputSource( stream ) );
   if ( errors.size() != 0 ) {
    throw new MappingException( "invalid configuration", (Throwable) errors.get( 0 ) );
   }
   doConfigure( document );
  }
  catch (DocumentException e) {
   throw new HibernateException( "Could not parse configuration: " + resourceName, e );
  }
  finally {
   try {
    stream.close();
   }
   catch (IOException ioe) {
    log.warn( "could not close input stream for: " + resourceName, ioe );
   }
  }
  return this;
 }

 

方法4

protected Configuration doConfigure(Document doc) throws HibernateException {
  Element sfNode = doc.getRootElement().element( "session-factory" );
  String name = sfNode.attributeValue( "name" );
  if ( name != null ) {
   properties.setProperty( Environment.SESSION_FACTORY_NAME, name );
  }
  addProperties( sfNode );
  parseSessionFactory( sfNode, name );

  Element secNode = doc.getRootElement().element( "security" );
  if ( secNode != null ) {
   parseSecurity( secNode );
  }

  log.info( "Configured SessionFactory: " + name );
  log.debug( "properties: " + properties );

  return this;
}

 

以上的只是把配置文件转换成流,再通过dom4j包来处理(不了解dom4j的朋友,把它给开苞吧),到方法4中都接点了。

 

上面红色部分就是写入配置文件的关键方法。

 

先说说addProperties( sfNode )方法

private void addProperties(Element parent) {
  Iterator itr = parent.elementIterator( "property" );
  while ( itr.hasNext() ) {
   Element node = (Element) itr.next();
   String name = node.attributeValue( "name" );
   String value = node.getText().trim();
   log.debug( name + "=" + value );
   properties.setProperty( name, value );
   if ( !name.startsWith( "hibernate" ) ) {
    properties.setProperty( "hibernate." + name, value );
   }
  }
  Environment.verifyProperties( properties );
 }

就是把标签property属性全部放到一个 properties参数中,properties是一个继承了Hashtable的类生成的对象。之后这个标签就都放这了,以后慢慢用吧。

 

再看看parseSessionFactory( sfNode, name )方法

private void parseSessionFactory(Element sfNode, String name) {
  Iterator elements = sfNode.elementIterator();
  while ( elements.hasNext() ) {
   Element subelement = (Element) elements.next();
   String subelementName = subelement.getName();
   if ( "mapping".equals( subelementName ) ) {
    
parseMappingElement( subelement, name );
   }
   else if ( "class-cache".equals( subelementName ) ) {
    String className = subelement.attributeValue( "class" );
    Attribute regionNode = subelement.attribute( "region" );
    final String region = ( regionNode == null ) ? className : regionNode.getValue();
    boolean includeLazy = !"non-lazy".equals( subelement.attributeValue( "include" ) );
    setCacheConcurrencyStrategy( className, subelement.attributeValue( "usage" ), region, includeLazy );
   }
   else if ( "collection-cache".equals( subelementName ) ) {
    String role = subelement.attributeValue( "collection" );
    Attribute regionNode = subelement.attribute( "region" );
    final String region = ( regionNode == null ) ? role : regionNode.getValue();
    setCollectionCacheConcurrencyStrategy( role, subelement.attributeValue( "usage" ), region );
   }
   else if ( "listener".equals( subelementName ) ) {
    parseListener( subelement );
   }
   else if ( "event".equals( subelementName ) ) {
    parseEvent( subelement );
   }
  }
 }

其实都是各自的方法set各自的东西,如果想看都怎么写的,那就一直点进去看看吧,比如第一个parseMappingElement( subelement, name );最后到下面的方法体中(3.6.0版本代码)

public void add(XmlDocument metadataXml) {
   final Document document = metadataXml.getDocumentTree();
   final Element hmNode = document.getRootElement();
   Attribute packNode = hmNode.attribute( "package" );
   String defaultPackage = packNode != null ? packNode.getValue() : "";
   Set<String> entityNames = new HashSet<String>();
   findClassNames( defaultPackage, hmNode, entityNames );
   for ( String entity : entityNames ) {
    hbmMetadataByEntityNameXRef.put( entity, metadataXml );
   }
   this.hbmMetadataToEntityNamesMap.put( metadataXml, entityNames );
  }

 

上面的一系列的方法,包含文件的检测啊,写入到hbmMetadataByEntityNameXRef与hbmMetadataToEntityNamesMap中。

 

在这里,根据我看过一篇博客中(地址:点我),在parseMappingElement( subelement, name );最后调用的方法是(3.3.0版本代码)

public Configuration addInputStream(InputStream xmlInputStream) throws MappingException {
try {
List errors = new ArrayList();
org.dom4j.Document doc = xmlHelper.createSAXReader( "XML InputStream", errors, entityResolver )
.read( new InputSource( xmlInputStream ) );
if ( errors.size() != 0 ) {
throw new InvalidMappingException( "invalid mapping", null, (Throwable) errors.get( 0 ) );
}
add( doc );
return this;
}
catch (DocumentException e) {
throw new InvalidMappingException( "input stream", null, e );
}
finally {
try {
xmlInputStream.close();
}
catch (IOException ioe) {
log.warn( "Could not close input stream", ioe );
}
}
}

 

上面的代码是(http://anonsvn.jboss.org/repos/hibernate/core/tags/hibernate-3.3.0.CR1/core/src/main/java/org/hibernate/cfg/Configuration.java)

这个版本时的代码,看清版本号3.3.0

再调用下面的add方法

 

protected void add(org.dom4j.Document doc) throws MappingException {
HbmBinder.bindRoot( doc, createMappings(), CollectionHelper.EMPTY_MAP );
}

/**
* Create a new <tt>Mappings</tt> to add class and collection
* mappings to.
*/
public Mappings createMappings() {
return new Mappings(
classes,
collections,
tables,
namedQueries,
namedSqlQueries,
sqlResultSetMappings,
imports,
secondPasses,
propertyReferences,
namingStrategy,
typeDefs,
filterDefinitions,
extendsQueue,
auxiliaryDatabaseObjects,
tableNameBinding,
columnNameBindingPerTable
);
}

会主动的实例化一个Mappings类。

 

以上都是3.3.0时的代码,目的就是建立ConfigurationMappings是一对多的关系,Mappings类作为桥梁实例化这些字段,而不添加一个Mappings类的引用

而最新的3.6.0版本中的代码,已经发生了变化。

 

之前Mappings是实体类,现在Mappings为接口,并在Configuration中有一个Mappings的实现类MappingsImpl,刚好是上面说的。

 

 

 

 

 

其实Configuration conf=new Configuration();的第一步,还会创建一个new SettingsFactory(),这个SettingsFactory类,就在下篇再细说吧。

 

总的来说,Configuration在new与config() 方法的调用,buildSessionFactory()的过程中。

 

1,加载xml文件,再解析,把property标签的内容放在properties中,properties是一个Map。

2,而把另一部分mapping标签的内容放到内容类MetadataSourceQueue的私有变量中。

3,调用buildSessionFactory()后,给相应的参数赋值,完成SessionFactory的创建。

 

如果想进一步的了解,对应xml第一个属性,都是都有一个方法来解析。

 

通过对这个类的观察,可以充分理解抽象工厂的使用,学习源代码,其实就是学习人家的设计模式,而且代码中加入了很多的方式防止因为一个配置不正确,导致的代码问题;并将错误写入日志,以供排查。

 

与3.3.0相比,最主要的是多了两个内部类:

MappingsImpl与MetadataSourceQueue。

 

当然其中一个方法,对后面的分析也是很深远的,就是setListeners(String type, Object[] listeners)这个方法中根据类型,增加事务处理监控,这个之后再深入吧。

 

看完这个,也许,你会发现其中有些东西搞错了,换理解有问题,那么,请您帮我指出,每一个错误的指出,都是我对hibernate理解的一次加深。

 

欢迎讨论。

 

 

 

分享到:
评论

相关推荐

    hibernate-configuration-3.0.dtd、hibernate-mapping-3.0.dtd

    而`hibernate-configuration-3.0.dtd`和`hibernate-mapping-3.0.dtd`是Hibernate 3.0版本中的两个核心文件,它们定义了Hibernate配置文件和映射文件的语法规则,是理解Hibernate工作原理的关键所在。 首先,我们来...

    hibernate-core-5.0.11.Final.jar

    2. **org.hibernate**:这是核心代码所在的主要包,下辖多个子包,涵盖了Hibernate的所有核心功能,如: - `configuration`:负责配置信息的读取和解析,包括XML配置文件和程序化配置。 - `entitymanager`:实现了...

    hibernate-release-4.3.10.Final.zip

    - **Configuration**:负责配置Hibernate,加载hibernate.cfg.xml文件,建立SessionFactory。 - **SessionFactory**:是线程安全的,用于创建Session实例,它是整个Hibernate的核心,管理实体类和数据库表的映射...

    hibernate-dtd-xsd约束文件

    在Hibernate中,`hibernate-mapping-3.0.dtd`和`hibernate-configuration-3.0.dtd`是针对Hibernate 3.0版本的配置文件的DTD文件。`hibernate-mapping-3.0.dtd`主要用于定义实体类(Entity)与数据库表之间的映射关系...

    hibernate-release-4.2.2.Final

    1. hibernate-core.jar:Hibernate的核心库,包含了ORM的主要功能,如实体管理、会话管理、查询语言等。 2. hibernate-entitymanager.jar:实现了JPA规范,提供对标准JPA API的支持。 3. hibernate-jpa-2.1-api.jar...

    hibernate-lib。rar

    《Hibernate核心库解析与应用详解》 Hibernate,作为一款强大的对象关系映射(ORM)框架,极大地简化了Java开发者在数据库操作中的工作。这个“hibernate-lib.rar”压缩包包含的是Hibernate的核心库,它是Hibernate...

    hibernate-release-4.3.9.Final.rar

    《Hibernate 4.3.9.Final:持久化框架的核心技术与实践》 Hibernate,作为Java领域中的一个著名ORM(对象关系映射)框架,它极大地简化了数据库操作,使得开发者能够以面向对象的方式来处理数据库交互。这次我们...

    hibernate-annotations-3.4.0.GA+hibernate-distribution-3.3.2.GA-dist

    《深入理解Hibernate 3.3.2与Annotations 3.4.0:核心特性与实践应用》 Hibernate作为Java领域中的一个强大ORM(对象关系映射)框架,为开发者提供了在Java应用程序中操作数据库的强大工具。它允许我们将数据库操作...

    sql2000与sql2005的hibernate-configuration

    - SessionFactory创建:使用`Configuration`类加载配置并建立SessionFactory,它是Hibernate的核心对象,负责管理会话和事务。 5. 示例配置: ```xml &lt;hibernate-configuration&gt; &lt;session-factory&gt; ...

    hibernate-core.zip

    - `SessionFactoryBuilder`和`Configuration`:负责读取Hibernate配置文件,构建SessionFactory。 - `Caching`:Hibernate支持缓存机制,如一级缓存(Session级别的缓存)和二级缓存(SessionFactory级别的缓存),...

    hibernate-release-4.2.3.lib.zip

    总结,`hibernate-release-4.2.3.Final.zip`中的lib文件夹包含了运行Hibernate应用所需的全部库文件,包括Hibernate核心库、JDBC驱动、缓存提供商等。通过理解和熟练运用这些知识点,开发者可以构建出高效、可靠的...

    hibernate-release-5.0.11.Final

    一、Hibernate核心概念 1. 对象关系映射(ORM):Hibernate通过映射Java类到数据库表,实现了对象与关系数据之间的桥梁,使得开发者可以使用面向对象的方式处理数据库操作。 2. Session:Session是Hibernate的主要...

    hibernate-release-5.2.10

    本文将围绕`hibernate-release-5.2.10`这一版本,详细探讨其核心特性、工作原理以及在实际项目中的应用。 一、Hibernate简介 Hibernate是一种开源的ORM框架,它允许开发者使用面向对象的方式进行数据库编程,避免了...

    hibernate-distribution-3.6.10.Final基本包

    三、Hibernate核心组件 1. Configuration:配置对象,用于读取Hibernate配置信息,如数据源、实体类等。 2. SessionFactory:会话工厂,负责创建Session对象,是线程安全的,应用启动时只创建一次。 3. Session:...

    hibernate-distribution-3.6.10.Final-dist.zip

    - lib目录:包含了Hibernate运行所需的全部依赖库,包括Hibernate核心库、JTA、JDBC驱动等。 - docs目录:提供了详细的API文档和用户手册,方便开发者查阅。 - examples目录:包含了一些示例代码,帮助开发者快速...

    hibernate-distribution-3.6.8.Final-dist

    2. **创建SessionFactory**:通过Hibernate的Configuration类加载配置文件并创建SessionFactory实例,它是Hibernate工作的核心。 3. **操作对象**:使用SessionFactory的openSession()方法创建Session对象,进行增...

    hibernate-release-5.0.6.Final

    1. Configuration:配置对象用于读取hibernate.cfg.xml配置文件,初始化SessionFactory。 2. SessionFactory:是线程安全的,负责创建Session实例,它是数据库会话工厂。 3. Session:代表一次数据库会话,负责执行...

    hibernate-dtd

    2. `hibernate-configuration-3.0.dtd`:这个DTD定义了`hibernate.cfg.xml`文件的结构,确保配置文件的正确性。 了解并掌握Hibernate的DTD文件,可以帮助开发者更准确地编写配置文件,避免因格式错误导致的运行时...

    hibernate-distribution-3.3.2.GA-dist.zip

    三、Hibernate 的核心组件 1. Configuration:配置 Hibernate,加载映射文件,建立 SessionFactory。 2. SessionFactory:是线程不安全的,负责创建 Session 对象,是整个应用的单例对象。 3. Session:是操作数据库...

    hibernate-3.2源码

    本文将基于Hibernate 3.2的源码,深入探讨其核心设计理念与实现机制。 一、Hibernate架构概览 Hibernate 3.2的架构设计遵循分层原则,主要包含以下几个关键组件: 1. API:提供了面向开发者的接口,如...

Global site tag (gtag.js) - Google Analytics