`

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约束文件(核心配置、映射文件)

    此压缩包内存在两个hibernate框架搭建时所用到的约束文件,分别是核心配置文件的约束、映射文件的约束,名称分别为hibernate-configuration-3.0.dtd、hibernate-mapping-3.0.dtd;

    hibernate-3.2完整源码包和4.x模块(ogm、search、validator等)版本包.txt

    Hibernate是开源的ORM对象关系映射框架,包括Session、SessionFactory、Transaction、Query、Criteria和Configuration六核心类和接口。

    hibernate学习资料

    Hibernate框架开发中环境配置,hibernate-configuration-3.0的核心配置文件

    最新Hibernate jar 架包(9个)

    slf4j-api-1.6.1.jar 这个包是必须的,因为在Hibernate的核心包中多处用到了,比如Configuration.class中用到了 slf4j-nop-1.6.1.jar 这个包是slf4j的实现类,所以也是必须的,注意实现类得和slf4j的版本要匹配 ...

    Hibernate的五个核心接口介绍.png

    Hibernate的五个核心接口 Configuration SessionFactory Session Transcation Query和Criteria

    Hibernate核心接口

    Hibernate的核心接口一共有5个,分别为:Session、SessionFactory、Transaction、Query和Configuration。

    Hibernate学习笔记和资料

    hibernate概述,hibernate入门Demo,hibernate配置文件详解(全局配置,实体类映射配置),配置实体规则,核心API详解(Configuration,sessionFactory,session,Transaction),hibernate中的对象状态以及刷新能缓存机制 ...

    Hibernate体系结构的概要图

    Hibernate的核心接口一共有6个,分别为:Session、SessionFactory、Transaction、Query、Criteria和Configuration。这6个核心接口在任何开发中都会用到。通过这些接口,不仅可以对持久化对象进行存取,还能够进行事务...

    hibernate4.3完整jar包

    Hibernate是一个开放源代码的对象关系映射框架,它对JDBC进行了非常轻量级的对象封装,使得Java...Hibernate的核心接口一共有6个,分别为:Session、SessionFactory、Transaction、Query、Criteria和Configuration。

    搞定J2EE:STRUTS+SPRING+HIBERNATE整合详解与典型案例 (1)

    12.2 Hibernate的核心 12.2.1 Configuration(配置Connection) 12.2.2 SessionFactory(Connection工厂) 12.2.3 Session(提供Connection) 12.3 使用Hibernate操作数据库的示例 12.3.1 创建数据库表 12.3.2 编写...

    Hibernate使用技巧汇总

    HibernateTemplate对Hibernate Session操作进行了封装,而 HibernateTemplate.execute方法则是一封装机制的核心 *在spring的配置文件里,移植了整个hibernate.cfg.xml的内容。

    hibernate api

     Hibernate的核心接口一共有5个,分别为:Session、SessionFactory、Transaction、Query和Configuration。这5个核心接口在任何开发中都会用到。通过这些接口,不仅可以对持久化对象进行存取,还能够进行事务控制。

    hibernate精华教程

    3.Hibernate的5个核心类或接口: (1)Configuration:用于解析hibernate.cfg.xml文件和XXXXX.hbm.xml文件,并创建SessionFactory对象。Configuration对象用于配置并且启动Hibernate。Hibernate应用通过Configuration...

    搞定J2EE:STRUTS+SPRING+HIBERNATE整合详解与典型案例 (2)

    12.2 Hibernate的核心 12.2.1 Configuration(配置Connection) 12.2.2 SessionFactory(Connection工厂) 12.2.3 Session(提供Connection) 12.3 使用Hibernate操作数据库的示例 12.3.1 创建数据库表 12.3.2 编写...

    搞定J2EE:STRUTS+SPRING+HIBERNATE整合详解与典型案例 (3)

    12.2 Hibernate的核心 12.2.1 Configuration(配置Connection) 12.2.2 SessionFactory(Connection工厂) 12.2.3 Session(提供Connection) 12.3 使用Hibernate操作数据库的示例 12.3.1 创建数据库表 12.3.2 编写...

    Hiberante中的五大核心接口.txt

    Hibernate的核心接口一共有5个,分别为:Session、SessionFactory、Transaction、Query和Configuration。这5个核心接口在任何开发中都会用到。通过这些接口,不仅可以对持久化对象进行存取,还能够进行事务控制。下面...

    Hibernate核心API

    主要知识点包括: 持久实例的生命周期状态 Session接口 Transaction接口 SessionFactory接口 Configuration接口 应用中所需要的JAR类库

    SSH的jar包.rar

    1.通过Configuration().configure();读取并解析hibernate.cfg.xml配置文件 2.由hibernate.cfg.xml中的读取并解析映射信息 3.通过config.buildSessionFactory();//创建SessionFactory 4.sessionFactory....

    从J2SE到J2EE知识点介绍

    (四) Hibernate 核心接口 194 1. Session接口 194 2. SessionFactory接口 194 3. Configuration类 194 4. Transaction接口 195 5. Query和Criteria接口 195 (五) Hibernate的安装和配置 195 1. 安装Hibernate 195 2....

    基于J2EE框架的个人博客系统项目毕业设计论文(源码和论文)

    本网站以xp为Web平台,JSP+Ajax+Servlet+JavaBean+Hibernate为网站实现技术,建立基于MySQL数据库系统的核心动态网页,实现博客网站前台及博客个人维护管理等功能模块。 1、 系统处理的准确性和及时性:系统处理的...

Global site tag (gtag.js) - Google Analytics