`
FlyAway2
  • 浏览: 111909 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

Hibernate源码解读——启动

    博客分类:
  • j2ee
 
阅读更多

 作为javar的必学框架,我相信Hibernate源码也是被研究过无数次了。不过,别人研究过不代表我就不需要看了。

 

这里我以我的视野简单的过一遍。各位iteye的朋友有时间可以看看。如何已经很熟悉这个了就不用看了,否则看也是浪费时间。我研究的方法非常简单,就是反复读源码,一遍不行,二遍,或者三遍。。。

 

从Hibernate源码看它的启动过程:

 

Hibernate的启动是从Configuration开始的。Configuration既是它的配置中心,也是它的启动最初点。

Configuration提供了几个重载的configure方法,用来读取配置,默认,当然就是hibernate.cfg.xml。

configure调用doConfigure,返回Configuration。

 

doConfigure(org.dom4j.Document doc)很重要:

protected Configuration doConfigure(org.dom4j.Document doc) throws HibernateException {
		//获取session-factory节点sfNode
		Element sfNode = doc.getRootElement().element( "session-factory" );
		String name = sfNode.attributeValue( "name" );
		if ( name != null ) {
			properties.setProperty( Environment.SESSION_FACTORY_NAME, name );
		}
		//处理sfNode的子节点property
		addProperties( sfNode );
		//处理sfNode的其他子节点,主要是mapping、listener、event
		parseSessionFactory( sfNode, name );

		Element secNode = doc.getRootElement().element( "security" );
		if ( secNode != null ) {
			parseSecurity( secNode );//处理doc的其他子节点,security,一般用的少
		}
		return this;
	}

 

 

mapping 是关键,类似下面的配置

<mapping resource="com/bjsxt/drp/business/itemmgr/model/DataDict.hbm.xml"/>

 

protected void parseMappingElement(Element subelement, String name) {
		Attribute rsrc = subelement.attribute( "resource" );
		Attribute file = subelement.attribute( "file" );
		Attribute jar = subelement.attribute( "jar" );
		Attribute pkg = subelement.attribute( "package" );
		Attribute clazz = subelement.attribute( "class" );	
		addResource( rsrc.getValue() );
		addJar( new File( jar.getValue() ) );
                 addFile( file.getValue() );
	}

 

 

常用的当然就是addResource,它调用addInputStream,然后是add(org.dom4j.Document doc),然后是HbmBinder.bindRoot( doc, createMappings(), CollectionHelper.EMPTY_MAP );

 

HbmBinder相当重要,他处理了Xxx.hbm.xml的各种配置;

——Walks an XML mapping document and produces the Hibernate configuration-time metamodel (the classes in the mapping)

 

 

 

 

bindRoot首先处理package属性,然后是其下面的各种元素:

filter-def

typedef

class:  通过bindRootClass-bindRootPersistentClassCommonValues处理class下的 property元素等

subclass

typedef

query

sql-query

import

database-object

 

else if ( "class".equals( elementName ) ) {
				RootClass rootclass = new RootClass();
				bindRootClass( element, rootclass, mappings, inheritedMetas );
				mappings.addClass( rootclass );
			}


---->>>
public static void bindRootClass(Element node, RootClass rootClass, Mappings mappings,
			java.util.Map inheritedMetas) throws MappingException {
		bindClass( node, rootClass, mappings, inheritedMetas );
		inheritedMetas = getMetas( node, inheritedMetas, true ); // get meta's from <class>
		bindRootPersistentClassCommonValues( node, inheritedMetas, mappings, rootClass );
	}

 

 

继续跟踪,我们发现,类似 Xxx.hbm.xml的配置,里面的class元素,都被放到了 RootClass 里面:

public class RootClass extends PersistentClass implements TableOwner

它是一个实际对数据进行封装的类,主要是封装了下面的 属性,及对应的setter、getter方法。

	private Property identifierProperty; //may be final
	private KeyValue identifier; //may be final
	private Property version; //may be final
	private boolean polymorphic;
	private String cacheConcurrencyStrategy;
	private String cacheRegionName;
	private boolean lazyPropertiesCacheable = true;
	private Value discriminator; //may be final
	private boolean mutable = true;
	private boolean embeddedIdentifier = false; // may be final
	private boolean explicitPolymorphism;
	private Class entityPersisterClass;
	private boolean forceDiscriminator = false;
	private String where;
	private Table table;
	private boolean discriminatorInsertable = true;
	private int nextSubclassId = 0;

 PersistentClass 也是很重要,——Mapping for an entity

 

 

 

bindClass主要对 class里面的属性进行处理;

而bindRootPersistentClassCommonValues是对class下元素进行处理;

 

bindRootPersistentClassCommonValues很重要,二级缓存标签cache 也是在这里进行处理的!

private static void bindRootPersistentClassCommonValues(Element node,
			java.util.Map inheritedMetas, Mappings mappings, RootClass entity)
			throws MappingException {

	// DB-OBJECTNAME
	Attribute schemaNode = node.attribute( "schema" );
	String schema = schemaNode == null ?
			mappings.getSchemaName() : schemaNode.getValue();

	Attribute catalogNode = node.attribute( "catalog" );
	String catalog = catalogNode == null ?
			mappings.getCatalogName() : catalogNode.getValue();

	Table table = mappings.addTable(
			schema,
			catalog,
			getClassTableName( entity, node, schema, catalog, null, mappings ),
			getSubselect( node ),
		entity.isAbstract() != null && entity.isAbstract().booleanValue()
		);
	entity.setTable( table );
	bindComment(table, node);

	// MUTABLE
	Attribute mutableNode = node.attribute( "mutable" );
	entity.setMutable( ( mutableNode == null ) || mutableNode.getValue().equals( "true" ) );

	// WHERE
	Attribute whereNode = node.attribute( "where" );
	if ( whereNode != null ) entity.setWhere( whereNode.getValue() );

	// CHECK
	Attribute chNode = node.attribute( "check" );
	if ( chNode != null ) table.addCheckConstraint( chNode.getValue() );

	// POLYMORPHISM
	Attribute polyNode = node.attribute( "polymorphism" );
	entity.setExplicitPolymorphism( ( polyNode != null )
		&& polyNode.getValue().equals( "explicit" ) );

	// ROW ID
	Attribute rowidNode = node.attribute( "rowid" );
	if ( rowidNode != null ) table.setRowId( rowidNode.getValue() );

	Iterator subnodes = node.elementIterator();
	while ( subnodes.hasNext() ) {

		Element subnode = (Element) subnodes.next();
		String name = subnode.getName();

		if ( "id".equals( name ) ) {
			// ID
			bindSimpleId( subnode, entity, mappings, inheritedMetas );
		}
		else if ( "composite-id".equals( name ) ) {
			// COMPOSITE-ID
			bindCompositeId( subnode, entity, mappings, inheritedMetas );
		}
		else if ( "version".equals( name ) || "timestamp".equals( name ) ) {
			// VERSION / TIMESTAMP
			bindVersioningProperty( table, subnode, mappings, name, entity, inheritedMetas );
		}
		else if ( "discriminator".equals( name ) ) {
			// DISCRIMINATOR
			bindDiscriminatorProperty( table, entity, subnode, mappings );
		}
		else if ( "cache".equals( name ) ) {
			entity.setCacheConcurrencyStrategy( subnode.attributeValue( "usage" ) );
			entity.setCacheRegionName( subnode.attributeValue( "region" ) );
			entity.setLazyPropertiesCacheable( !"non-lazy".equals( subnode.attributeValue( "include" ) ) );
		}
	}

	// Primary key constraint
	entity.createPrimaryKey();

	createClassProperties( node, entity, mappings, inheritedMetas );
}

 

 

 

这个类,我还没完全看懂,众所周知,hibernate的配置相当繁多复杂。我就常常记不住,有一次面试的时候,面试官问我hibernate的父类子类继承关系怎么配置,我记不得,所以也说不清。。。 给他留下不好印象。启动,先说到这里。有时间再仔细看看。

 

总之,configure之后,hibernate的配置就生效,可以使用了!

 

比如,通过配置获取可使用的 SessionFactory :

factory = cfg.buildSessionFactory();//  获取 factory 是hibernate 许多框架发挥巨大作用的最基础!

等等。

 

当然,我们一般不用直接通过,Configuration的静态方法configure来启动hibernate。在web应用中,我们通过web容器的相关配置来启动。

 

比如,在和struts集成(没有spring)的时候,我们通常写一个类似HibernateUtil负责从配置文件中获取、关闭SessionFactory :

public class HibernateUtils {

	private static SessionFactory factory;
	
	static {
		try {
			Configuration cfg = new Configuration().configure();
			factory = cfg.buildSessionFactory();
		}catch(Exception e) {
			e.printStackTrace();
		}
	}
	
	public static SessionFactory getSessionFactory() {
		return factory;
	}
	
	public static Session getSession() {
		return factory.openSession();
	}
	
	public static void closeSession(Session session) {
		if (session != null) {
			if (session.isOpen()) {
				session.close();
			}
		}
	}
}

 

 

当然,这其实还是要

Configuration cfg = new Configuration().configure();
   factory = cfg.buildSessionFactory();

 

但由于他是静态初始化块的,所以配置只会被读取一次。当然,session还是要每次来获取的:

factory.openSession(),(是否每次打开同一个session根据情况需要)

factory还提供了api来获取不同的session:

openSession()

openSession(Connection connection)

openSession(Interceptor interceptor)

getCurrentSession()

openStatelessSession()

openStatelessSession(Connection connection)

 

 

另外,我们可以通过其他方式启动hibernate,插件方式:

import org.apache.struts.action.PlugIn;
import org.apache.struts.action.ActionServlet;
import org.apache.struts.config.ModuleConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletContext;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

public class HibernatePlugIn implements PlugIn {
	public void destroy() {
	}

	public void init(ActionServlet servlet, ModuleConfig config)
			throws ServletException {
		try {
			ServletContext context = servlet.getServletContext();
			SessionFactory sf = new Configuration().configure()
					.buildSessionFactory();
			context.setAttribute("org.hibernate.SessionFactory", sf);
		} catch (Exception ex) {
			ex.printStackTrace();
		}
	}
}

 然后在struts-config.xml配置插件信息:

 

 <plug-in className="homepage.HibernatePlugIn">    <set-property property="configFilePath"   value="/WEB-INF/classes/hibernate.cfg.xml" />    <set-property property="storeInServletContext" value="true" /> 

</plug-in>
然后利用java.naming.Context,java.naming.InitiaContext来查找
Context ct = new InitialContext();     

sessions=(SessionFactory) ct.lookup("hibernate/session_factory");     

session=sessions.openSession();

然后再封装成类似HibernateUtil的类,然后就可以在action中使用了。

 

 

如果集成在spring中,我们通常有如下的配置:

 <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
  <property name="configLocation">
   <value>classpath:hibernate.cfg.xml</value>
  </property> 
 </bean>    

从而通过org.springframework.orm.hibernate3.LocalSessionFactoryBean读取hibernate配置,进而在必要的时候使用hibernateapi,可以说,它这个包装是很有用的。

 

spring提供有用的HibernateDaoSupport类,简化业务中对数据库的交互:

我们在业务中(通常是dao层)只要继承HibernateDaoSupport,然后再在spring对齐做相应的配置,就可以直接使用HibernateDaoSupport提供的getHibernateTemplate()来获取所需的hibernate session相关方法了,如

save、load、query、update、delete等

 

分享到:
评论

相关推荐

    Hibernate 孙卫琴 源码

    《Hibernate 源码解析——孙卫琴解读》 Hibernate,作为Java领域中著名的对象关系映射(ORM)框架,极大地简化了数据库操作,使得开发者能够以面向对象的方式来处理数据库事务。孙卫琴,一位在Java社区有深厚影响力...

    孙卫琴hibernate source code2

    《孙卫琴Hibernate源码解析第二部分》 在IT领域,Hibernate作为一个强大的对象关系映射(ORM)框架,极大地简化了Java开发者与数据库之间的交互。孙卫琴老师的“Hibernate源码解析”系列深入剖析了Hibernate的内部...

    spring 源码中文注释

    这份"spring 源码中文注释"包含了对Spring框架源码的详细解读,对于理解其工作原理、优化代码以及定制化开发具有重要意义。 首先,我们来看看Spring的核心组件——IoC容器。IoC容器是Spring的核心,它负责管理对象...

    Java毕业设计——学校管理系统设计与实现(源码+数据库).zip

    《Java毕业设计——学校管理系统设计与实现》是一...以上内容仅是对该毕业设计项目的一般性解读,具体实现细节还需参考源码和数据库设计。通过这个项目,学生可以深入理解Java Web开发的全流程,提升实际问题解决能力。

    基于jsp+ssh的人力外包企业专用HR管理平台源码数据库.zip

    "基于jsp+ssh的人力外包企业专用HR管理平台源码数据库" 这个标题揭示了我们讨论的核心内容是一个专为人力外包公司设计的HR管理系统,它的技术实现是基于Java的Web开发框架——JSP(JavaServer Pages)和SSH(Spring...

    oldXerces-J-bin.2.0.0.beta4.zip

    根据文件名称列表中的"**xerces-2_0_0_beta4**",我们可以推断压缩包内包含了Xerces-J 2.0.0 beta4版本的源码或者编译后的二进制文件,可能包括jar包、文档、示例代码或API接口说明等资源。 **知识点详解:** 1. *...

    spring-1.0-rc1.zip

    本篇将聚焦于Spring的初代版本——Spring 1.0-rc1,通过对源码的深入解读,揭示其设计理念和核心功能,帮助读者理解Spring框架的基础架构和实现原理。 Spring 1.0-rc1是Spring框架发展的重要里程碑,它的代码量相对...

    spring例子: jpetstore

    标题 "spring例子: jpetstore" 提到的是一个基于Spring框架的应用示例——JPetStore。这个项目是Spring官方提供的一个经典示例,用于展示如何使用Spring框架来构建Web应用程序。它是一个小型的在线宠物商店,包含了...

    一个通讯录管理系统20240601121001

    《通讯录管理系统的设计与实现——基于Java技术》 在信息技术高度发达的今天,通讯录管理系统已经成为日常生活和工作中不可或缺的一部分。本文将围绕一个基于Java技术的通讯录管理系统进行深入探讨,旨在帮助读者...

    spring技术内幕-深入解析spring架构与设计原理

    本书将通过详细的案例分析和源码解读,帮助读者深入了解Spring的每个模块,从而在实际项目中更加得心应手地运用Spring框架。通过对这些核心概念的掌握,开发者不仅可以提升个人技术水平,还能提高团队协作效率,实现...

    java 高级架构进阶学习

    - **MyBatis源码分析**:解读MyBatis的工作流程、执行过程及SQL映射机制。 - **事务管理**:讨论非传统事务处理方式——柔性事务的概念及其优势。 - **MySQL优化**:分享MySQL性能调优技巧,包括索引优化、查询...

    JAVA语言考试系统的设计与实现(论文+源代码+文献综述+外文翻译+开题报告).rar

    首先,让我们关注核心部分——JAVA语言考试系统的实现。在Java平台上,这样的系统通常基于B/S(浏览器/服务器)架构,采用MVC(模型-视图-控制器)设计模式。MVC模式将业务逻辑、用户界面和数据存储分离,使得代码更...

    Information:科创服务器源代码

    "Information:科创服务器源代码" 这个标题揭示了我们要讨论的核心内容——科创服务器的源代码。"科创"可能指的是科技创新或科技创业项目,而"服务器源代码"则是指用于构建和运行该科创项目所使用的服务器端程序的...

Global site tag (gtag.js) - Google Analytics