先扯二句蛋:做Java也有很久了,安卓也搞了半年,回想自己当初学习java,j2ee的时候,全靠自己,没有老师,没有同学,书籍就是老师,搜索引擎就是同学,磕磕绊绊下来,终于有所心得,从今天开始准备好好的写一些博客,希望能帮助到那些刚上路,或者在路上却有些迷茫的童鞋````
最近有在研究hibernate这个框架的源码,所以这一阶段会将自己的研究进度和心得用简单的方式贴出来,希望帮到大家的同时,大家也能指出其中的问题,一起讨论,共同进步!(注意:这是源码分析,需要对hibernate有一定了解,起码使用过,所以没有使用过hibernate的童鞋还是先去使用使用在来看吧,不然只能一头雾水`````)
那么就从头开始,且听我细细道来:
hibernate大家都用过,使用下面这个东西大家应该都很熟悉
Configuration cfg = new Configuration().configure();
SessionFactory factory = cfg.buildSessionFactory();
这样就获取到了我们Dao层中所需要的SessionFactory了
那么configure()这个方法中做了什么?上源码
public Configuration configure() throws HibernateException {
configure( "/hibernate.cfg.xml" );
return this;
}
看,这里就是去加载解析/hibernate.cfg.xml去了,显然是用configure(String resource)方法,这个方法做了什么?上源码
public Configuration configure(String resource) throws HibernateException {
LOG.configuringFromResource( resource ); //打了个日志
InputStream stream = getConfigurationInputStream( resource ); //获取这个xml文件的输入流
return doConfigure( stream, resource );//用这个输入流去生成orm映射的对象了!
}
那doConfigure( stream, resource )做了什么?上源码
protected Configuration doConfigure(InputStream stream, String resourceName) throws HibernateException {
try {
ErrorLogger errorLogger = new ErrorLogger( resourceName );
Document document = xmlHelper.createSAXReader( errorLogger, entityResolver )
.read( new InputSource( stream ) );//这里就用这个输入流去生成一个Document 对象了,很显然,hibernate使用了SAX解析
if ( errorLogger.hasErrors() ) {
throw new MappingException( "invalid configuration", errorLogger.getErrors().get( 0 ) );
}
doConfigure( document );//看,再一次调用了重载的 doConfigure( Document document )方法
}
catch (DocumentException e) {
throw new HibernateException( "Could not parse configuration: " + resourceName, e );
}
finally {
try {
stream.close();
}
catch (IOException ioe) {
LOG.unableToCloseInputStreamForResource( resourceName, ioe );
}
}
return this;
}
那么重载的 doConfigure( Document document )方法中做了什么?上源码
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.configuredSessionFactory( name );
LOG.debugf( "Properties: %s", properties );
return this;
}
很显然,这个方法处理了两个节点:session-factory和security
session-factory这个节点很是熟悉啊,自然是用来指明各个映射文件的
security节点再议
parseSessionFactory( sfNode, name );就是去利用这个节点去找到各个映射文件,然后做映射,完成orm
那他做了啥?上源码
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 );
}
}
}
这里处理了3个节点mapping,class-cache,collection-cache,mapping节点很是熟悉啊,这就是咱为每个domain对象做的映射文件啊,其他两再议
处理mapping节点时调用了parseMappingElement( subelement, name );,那他做了啥?上源码
private void parseMappingElement(Element mappingElement, String name) {
final Attribute resourceAttribute = mappingElement.attribute( "resource" );
final Attribute fileAttribute = mappingElement.attribute( "file" );
final Attribute jarAttribute = mappingElement.attribute( "jar" );
final Attribute packageAttribute = mappingElement.attribute( "package" );
final Attribute classAttribute = mappingElement.attribute( "class" );
if ( resourceAttribute != null ) {
final String resourceName = resourceAttribute.getValue();
LOG.debugf( "Session-factory config [%s] named resource [%s] for mapping", name, resourceName );
addResource( resourceName );
}
else if ( fileAttribute != null ) {
final String fileName = fileAttribute.getValue();
LOG.debugf( "Session-factory config [%s] named file [%s] for mapping", name, fileName );
addFile( fileName );
}
else if ( jarAttribute != null ) {
final String jarFileName = jarAttribute.getValue();
LOG.debugf( "Session-factory config [%s] named jar file [%s] for mapping", name, jarFileName );
addJar( new File( jarFileName ) );
}
else if ( packageAttribute != null ) {
final String packageName = packageAttribute.getValue();
LOG.debugf( "Session-factory config [%s] named package [%s] for mapping", name, packageName );
addPackage( packageName );
}
else if ( classAttribute != null ) {
final String className = classAttribute.getValue();
LOG.debugf( "Session-factory config [%s] named class [%s] for mapping", name, className );
try {
addAnnotatedClass( ReflectHelper.classForName( className ) );
}
catch ( Exception e ) {
throw new MappingException(
"Unable to load class [ " + className + "] declared in Hibernate configuration <mapping/> entry",
e
);
}
}
else {
throw new MappingException( "<mapping> element in configuration specifies no known attributes" );
}
}
很长,本着解决主要矛盾,忽略次要矛盾的马列哲学思想,我们还是来关注我们最熟悉的,用class来配置,也就是上面的
else if ( classAttribute != null ) {
final String className = classAttribute.getValue();
LOG.debugf( "Session-factory config [%s] named class [%s] for mapping", name, className );
try {
addAnnotatedClass( ReflectHelper.classForName( className ) );
}
catch ( Exception e ) {
throw new MappingException(
"Unable to load class [ " + className + "] declared in Hibernate configuration <mapping/> entry",
e
);
}
两个LOG.debugf输出的文字很熟悉吧,就是hibernate启动时常常看见的,控制台打出的日志
那么 addAnnotatedClass( ReflectHelper.classForName( className ) );就是正式进入解析阶段了,且看具体做了什么,
首先不着急,我们看看ReflectHelper.classForName(className ),从名字就可以看出来用了反射技术去从className这个名字反射出一个类出来,暂时把他当做一个黑箱好了,只要知道传入一个对的名字就可以得到一个正确的Class类就ok了。
在得到类后传入看看做了啥:
@SuppressWarnings({ "unchecked" })
public Configuration addAnnotatedClass(Class annotatedClass) {
XClass xClass = reflectionManager.toXClass( annotatedClass );
metadataSourceQueue.add( xClass );
return this;
}
言简意赅,用了一个ReflectionManager对象的toXClass将我们的Class变成了Hibernate自定义的XClass,然后在metadataSourceQueue这个队列中加入了这个XClass,然后一个个映射就出炉了!以后我们就直接使用内存中的队列metadataSourceQueue就ok了
整个解析过程就是这个样子,看Hibernate源码果真是一种享受,很通俗易懂,言简意赅,不想某些公司的项目代码,简直一团乱麻!
ok,不抱怨了,且看几个细节问题,XClass究竟为何物,为何要将Class转化为XClass,MetadataSourceQueue又是何物?
且听下回分解
分享到:
相关推荐
标题:hibernate源码分析一[启动过程] 在深入探讨Hibernate框架的启动过程之前,我们首先需要了解几个核心的概念和类,它们是Hibernate启动流程的基石。 ### 1. 关键类与接口 #### Environment类 `Environment`类...
Hibernate 源码分析过程 Hibernate 是一个基于 Java 的 ORM(Object-Relation Mapping)框架,允许开发者使用面向对象的方式与关系数据库交互。在本文中,我们将对 Hibernate 的源码进行深入分析,并探讨其核心特性...
**Hibernate源码分析** Hibernate,一个著名的开源Java对象关系映射(ORM)框架,通过将Java对象和数据库表之间的映射关系自动化,极大地简化了数据访问层的开发工作。本篇将深入探讨Hibernate的源码,揭示其执行...
**hibernate源码分析:启动过程** 在深入探讨Hibernate启动过程之前,首先需要了解Hibernate是什么。Hibernate是一个开源的对象关系映射(ORM)框架,它为Java开发人员提供了一种在Java应用程序中操作数据库的方式...
- 错误排查:当遇到问题时,源码分析能更准确地定位问题所在,提高解决问题的效率。 - 自定义扩展:熟悉源码后,我们可以根据需求自定义拦截器、事件监听器等,实现特定功能。 总结来说,Hibernate源码解析是一个...
在阅读《Hibernate源码解析(三)》的过程中,配合hibernate源码分析(三).docx文档,读者可以更直观地理解这些概念,并可能涉及具体的类和方法,如`Query`、`SessionFactoryBuilder`、`EntityPersister`等。...
Hibernate源码分析有助于深入理解其内部机制,提高开发效率,优化数据库操作性能。 1. **Hibernate核心模块(hibernate-core)** Hibernate的核心模块包含了ORM框架的主要功能,如实体管理、查询语言(HQL)、事件...
**hibernate源码分析** Hibernate 是一个开源的Java库,它为对象关系映射(ORM)提供了强大的支持。在Java编程中,ORM允许开发者使用面向对象的方式来操作数据库,而无需编写大量的SQL语句,从而提高了开发效率和...
**Hibernate 源码分析** Hibernate 是一个开源的 Java 库,它作为对象关系映射(ORM)框架,为开发者提供了在 Java 应用程序中管理数据库数据的强大工具。Hibernate 3.2 版本是 Hibernate 系列的一个重要里程碑,...
标题"传智播客hibernate源码"暗示了这是一个关于Hibernate框架的源代码学习资源,可能包含了对Hibernate框架内部机制的深入解析,以及如何在实际项目中应用Hibernate的相关示例。 描述中的内容重复,进一步确认了这...
源码分析会展示这些查询API的底层实现,以及它们如何转换为SQL语句执行。 六、第二级缓存与查询缓存 为了提高性能,Hibernate支持二级缓存和查询缓存。二级缓存可以存储已加载的实体,减少对数据库的访问;查询...
源码分析是深入理解其工作原理的关键,特别是对于那些希望优化性能、解决特定问题或者扩展其功能的开发者来说。下面我们将详细探讨Hibernate的核心组件和工作流程。 1. **对象关系映射(ORM)**:Hibernate通过ORM...
在Hibernate源码的学习过程中,我们可以深入理解ORM的工作原理,提高我们的Java开发技能,并且能够更好地优化数据库操作。 一、Hibernate核心组件 1. Configuration:配置对象,负责读取hibernate.cfg.xml文件,...
源码分析对于开发者来说,是提升技术水平和深入理解框架原理的关键步骤。 **Struts** 是一个基于MVC(Model-View-Controller)设计模式的Java Web框架,主要负责处理用户请求和控制业务流程。它的核心是Action...
在Java的持久化框架中,Hibernate是一个非常流行的ORM(对象关系映射)工具,它极大地简化了数据库操作。本文将深入探讨Hibernate性能优化中的一个重要概念——一级缓存,并结合给出的压缩包文件“hibernate_cache_...
《精通Hibernate源码Chapter5:Java对象持久化技术详解》 在Java开发中,Hibernate作为一款强大的对象关系映射(ORM)框架,极大地简化了数据库操作。深入理解Hibernate的源码,不仅能帮助开发者提高工作效率,还能...
hibernate学习笔记hibernate优化hibernate源码分析hibernate学习笔记hibernate优化hibernate源码分析hibernate学习笔记hibernate优化hibernate源码分析
传智播客李勇hibernate源码1-20课,目录如下:01_hibernate介绍与动手入门体验;02_hibernate入门案例的细节分析; 03_hibernate入门案例的代码优化; 04_Session接口及get|load|persist方法 05_实体对象的三种状态...