上一篇: 下一篇:
一切从配置开始吧!
对于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时的代码,目的就是建立Configuration和Mappings是一对多的关系,用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 3.0版本中的两个核心文件,它们定义了Hibernate配置文件和映射文件的语法规则,是理解Hibernate工作原理的关键所在。 首先,我们来...
2. **org.hibernate**:这是核心代码所在的主要包,下辖多个子包,涵盖了Hibernate的所有核心功能,如: - `configuration`:负责配置信息的读取和解析,包括XML配置文件和程序化配置。 - `entitymanager`:实现了...
在Hibernate中,`hibernate-mapping-3.0.dtd`和`hibernate-configuration-3.0.dtd`是针对Hibernate 3.0版本的配置文件的DTD文件。`hibernate-mapping-3.0.dtd`主要用于定义实体类(Entity)与数据库表之间的映射关系...
1. hibernate-core.jar:Hibernate的核心库,包含了ORM的主要功能,如实体管理、会话管理、查询语言等。 2. hibernate-entitymanager.jar:实现了JPA规范,提供对标准JPA API的支持。 3. hibernate-jpa-2.1-api.jar...
《Hibernate核心库解析与应用详解》 Hibernate,作为一款强大的对象关系映射(ORM)框架,极大地简化了Java开发者在数据库操作中的工作。这个“hibernate-lib.rar”压缩包包含的是Hibernate的核心库,它是Hibernate...
《Hibernate 4.3.9.Final:持久化框架的核心技术与实践》 Hibernate,作为Java领域中的一个著名ORM(对象关系映射)框架,它极大地简化了数据库操作,使得开发者能够以面向对象的方式来处理数据库交互。这次我们...
《深入理解Hibernate 3.3.2与Annotations 3.4.0:核心特性与实践应用》 Hibernate作为Java领域中的一个强大ORM(对象关系映射)框架,为开发者提供了在Java应用程序中操作数据库的强大工具。它允许我们将数据库操作...
- SessionFactory创建:使用`Configuration`类加载配置并建立SessionFactory,它是Hibernate的核心对象,负责管理会话和事务。 5. 示例配置: ```xml <hibernate-configuration> <session-factory> ...
- `SessionFactoryBuilder`和`Configuration`:负责读取Hibernate配置文件,构建SessionFactory。 - `Caching`:Hibernate支持缓存机制,如一级缓存(Session级别的缓存)和二级缓存(SessionFactory级别的缓存),...
总结,`hibernate-release-4.2.3.Final.zip`中的lib文件夹包含了运行Hibernate应用所需的全部库文件,包括Hibernate核心库、JDBC驱动、缓存提供商等。通过理解和熟练运用这些知识点,开发者可以构建出高效、可靠的...
一、Hibernate核心概念 1. 对象关系映射(ORM):Hibernate通过映射Java类到数据库表,实现了对象与关系数据之间的桥梁,使得开发者可以使用面向对象的方式处理数据库操作。 2. Session:Session是Hibernate的主要...
本文将围绕`hibernate-release-5.2.10`这一版本,详细探讨其核心特性、工作原理以及在实际项目中的应用。 一、Hibernate简介 Hibernate是一种开源的ORM框架,它允许开发者使用面向对象的方式进行数据库编程,避免了...
- **Configuration**:负责配置Hibernate,加载hibernate.cfg.xml文件,建立SessionFactory。 - **SessionFactory**:是线程安全的,用于创建Session实例,它是整个Hibernate的核心,管理实体类和数据库表的映射...
三、Hibernate核心组件 1. Configuration:配置对象,用于读取Hibernate配置信息,如数据源、实体类等。 2. SessionFactory:会话工厂,负责创建Session对象,是线程安全的,应用启动时只创建一次。 3. Session:...
- lib目录:包含了Hibernate运行所需的全部依赖库,包括Hibernate核心库、JTA、JDBC驱动等。 - docs目录:提供了详细的API文档和用户手册,方便开发者查阅。 - examples目录:包含了一些示例代码,帮助开发者快速...
2. **创建SessionFactory**:通过Hibernate的Configuration类加载配置文件并创建SessionFactory实例,它是Hibernate工作的核心。 3. **操作对象**:使用SessionFactory的openSession()方法创建Session对象,进行增...
1. Configuration:配置对象用于读取hibernate.cfg.xml配置文件,初始化SessionFactory。 2. SessionFactory:是线程安全的,负责创建Session实例,它是数据库会话工厂。 3. Session:代表一次数据库会话,负责执行...
2. `hibernate-configuration-3.0.dtd`:这个DTD定义了`hibernate.cfg.xml`文件的结构,确保配置文件的正确性。 了解并掌握Hibernate的DTD文件,可以帮助开发者更准确地编写配置文件,避免因格式错误导致的运行时...
三、Hibernate 的核心组件 1. Configuration:配置 Hibernate,加载映射文件,建立 SessionFactory。 2. SessionFactory:是线程不安全的,负责创建 Session 对象,是整个应用的单例对象。 3. Session:是操作数据库...
本文将基于Hibernate 3.2的源码,深入探讨其核心设计理念与实现机制。 一、Hibernate架构概览 Hibernate 3.2的架构设计遵循分层原则,主要包含以下几个关键组件: 1. API:提供了面向开发者的接口,如...