- 浏览: 923089 次
- 性别:
- 来自: 北京
文章分类
- 全部博客 (322)
- Hibernate研究&源码 (27)
- Server (10)
- Coder碎语 (64)
- EnglishMulling (11)
- About XML (1)
- persistence (12)
- Core Java & OO (23)
- Java EE (6)
- JavaScript/JSON/Ajax/ext... (22)
- 我的读书笔记 (16)
- Source Codes Study (29)
- workFlow/jBPM (22)
- OFBiz: Open For Business (1)
- 项目积累 (21)
- srcStudy_acegi (1)
- Cache/Ehcache... (9)
- Java Test/JUnit.. (7)
- maven/ant (2)
- 设计模式 (1)
- SOA/cxf/ws-security (2)
- Android (4)
- 云计算/Hadoop (2)
- 加密/签名 (1)
- 正则表达式 (1)
- htmlparser (1)
- 操作系统 (5)
- DB (1)
最新评论
-
天使建站:
这里这篇文章更详细 还有完整的实例演示:js跳出循环 ...
jQuery中each的break和continue -
heshifk:
刚刚我也遇到同样的问题,然后就在纠结为什么不能直接使用brea ...
jQuery中each的break和continue -
masuweng:
不错写的.
集万千宠爱于一身的SessionImpl:get研究(四): Hibernate源码研究碎得(8) -
muzi131313:
这个老是忘,做一下笔记还是挺好的
jQuery中each的break和continue -
lg068:
data = data.replace("\n&qu ...
项目小经验: eval与回车符
上一篇花了很长时间梳理了下SessionImplementor接口与Hibernate里其它关键类和接口的关系并画出类图,最后得出"集万千宠爱于一身的SessionImpl"标题.本篇将接着往下走,下面先看第二句 EntityPersister persister;
声明了一个变量persister.(写到这有两种选择,一是像对SessionImplementor一样对这个EntityPersister接口好好研究一番,这样的话研究的很细,不过一个突出的问题就是由get方法牵连出很多点,分散精力;另一选择是把这个EntityPersister放在当前DefaultLoadEventListener类里结合它的具体应用来有个初步的认识. ... 现在尝试第二种选择,由于对SessionImplementor的研究是用第一种方法来展开的,看看这第二种选择有什么优缺点,再进一步来看如何与第一种结合起来以达到优势互补.)
有了上面的研究策略,这样把DefaultLoadEventListener类里的第62行至第76行拿出来做为一个意群(借用高考语文阅读训练中的一个术语)整体研究.
先看persister这个变量的声明方式,这里在第62行并没有对其赋值,结合项目中的一些经验,这样的声明是有一定的风险的,处理不好就报NullPointerException了.
先说说项目中遇到的类似情况及是怎么报异常的:
这样的一个异常容易发生在MVC端,
假设在C端有如下的处理逻辑:
Result result;
if(parameterConditionOne){
result = conditionOneProgram.getResult();
}else if (parameterConditionTwo){
result = conditionTwoProgram.getResult();
}
.................
result.setXXX(); // --- A
看上面的代码,若两个条件都不满足的话,在A处就会报NullPointerException,原因就在于分析情况时没有考虑全就造成现在这样的漏网之鱼.若在else if后再加一个else分枝呢?这样也是有值得注意的地方的,是否在非parameterConditionOne非parameterConditionTwo时就一定是else里的情况呢?
看Hibernate是怎么处理类似的麻烦事的:
在源码里71至76行的判断及异常处理.也就是说在经过if...else的赋值后再看这个persister是否这空,若为空就抛出一个HibernateException,这样把NullPointerException这样很唐突很底层的异常转为更为specific地异常.
现在看了Hibernate这里的处理方法后,佩服Hibernate的同时,也感觉到自己的成长,这样也就更加坚定了自己研究源码.
上面这段让我想起了自己项目中的一个Bug,现在再回到Hibernate的处理逻辑中.
第一个分支,即:event.getInstanceToLoad() != null 也就是说若event在初始化时传入并设置了instanceToLoad属性,这当然不是get方法时的调用情况了,BTW:Session接口中的load(Object object, Serializable id)方法就是这样的情况:在初始化LoadEvent事例时把load方法传入的Object对象再次传给LoadEvent的构造方法,从而就赋给了instanceToLoad属性.
若是这样的已初始化了instanceToLoad属性,persister的初始化就不同了,即通过source.getEntityPersister来返回,这样好像也能说的过去,毕竟那个instance已经在persistenceContext里存在了,这个instance也已经绑定了与之对应的EntityPersister了,也就不用再new一个EntityPersister的实现类对象了.在这里需要做的就是把event里的EntityClassName赋下值,现在的猜想是若传入了instanceToLoad就没有再传相应类的名字.这也很好理解,毕竟一个instanceToLoad本身就已经带了很丰富的内容.
source.getEntityPersiter()
与event.getInstanceToLoad() != null相反的是没有传入instanceToLoad对象,这种情况下我猜想是Hibernate在此时利用如下语句new出来一个与当前EntityClassName对应的EntityPersister实现类对象.
persister = source.getFactory().getEntityPersister( event.getEntityClassName());
追着源码看,并没有找到我猜想的那个new,那两种getEntityPersister有什么区别?也就是说若instanceToLoad不为null时的source.getEntityPersister与instanceToLoad为null时的source.getFactory().getEntityPersister两种有什么不同?这样就落在getFactory有什么用?
...............
从表面上来看是落在getFactory的作用上,但若往深入地看时发现,source.getEntityPersister实质上也是调用getFactory,而真正不同的是,这个方法中又调用了SessionImpl类里的guessEntityName方法,顾名思义,就是根据传入的Object对象来猜出这个Object在Hibernate里的Entity名字,不过还想往下问的是这样guess出来的名字与利用Object的反射得到的className有什么不同?毕竟LoadEvent里的getEntityClassName就是通过Class类的getName()方法获得的.这个问题先放这吧.
接着往下走,就是看ID是用什么类来表示的?是Long?是Integer?是String?并把这个类型与xxx.hbm.xml中的配置的类型做比较,若不符的话就抛出TypeMismatchException,我觉得这样的比较意义倒不是很大,或者说我不大理解为什么要这样比较?像一个Long型的id若用一个int型的值来表达时也不是不可以的吧?当然只要那个实际的值别超过int类型的范围,不过不理解归不理解,在使用时还是一定注意这个问题的.
这里还有一个问题:
persister.getIdentifierType().isComponentType() && EntityMode.DOM4J == event.getSession().getEntityMode()
怎么上面这个条件成立时就不用来比较了呢?当然若是componentType的话就没有明显的一个className了,这倒是一个原因,但这与EntityMode.DOM4J又有什么关系呢?这个问题还是只能先放这了.
下面又有一个新类EntityKey,不禁要问这个类是干啥的?为什么叫EntityKey呢?这样这个onLoad方法在每次调用时都new出来一个这样的对象是不是很是浪费?好像是JVM在每new一个对象时很耗资源的.能不能像Spring所提倡的那样最好用单例?又是什么因素制约着不能用单例呢?带着这些问题看EntityKey这个类的源码.
看这个类的源码发现与其它的类并没什么特殊的联系.自身除了三个方法外,也没有特别的.
这三个方法分别为private的generateHashCode与访问修饰为默认的serialize还有一个static且返回值为Entity的deserialize方法.这个deserialize方法没什么可说的,它自身就是一个工厂方法,返回一个EntityKey对象.
先看generateHashCode方法,这个方法也只是在EntityKey的构造方法中调用一次,对传入构造方法里的各个参数分别调用它们的hashCode方法并最终拼出一值赋给EntityKey的属性hashCode,这样也就能多多少少地了为什么叫key了.那这个key又具体怎么用呢?只能在它的具体应用中来看了.这让我想起了现在项目中通过字符串的方式拼出来的值作为自制缓存中key来使用了,为什么不用类的hasCode呢?那样的话显得的更专业.
再看serialize这个方法,它将EntityKey里的属性通过writeObject方法写进传入的ObjectOutputStream参数中?为什么要这样呢?这个serialize方法在什么情况下调用?想达到什么效果?是要写入本地文件中吗?追着看了看没看出什么门道,就先放在这吧.
从EntityKey返回到DefaultLoadEventListener类里的onLoad方法.下面将根据loadType是否为isNakedEntityReturned与LockMode是否为LockMode.NONE来调用不同的load方法,这里有三个不同的方法,依次是load,proxyOrLoad,lockAndLoad.这三个方法中除了第三个方法lockAndLoad多一个SessionImplementor型的参数外,都接收前面准备好的或onLoad传来的四个参数:event, persister, keyToLoad, loadType.
大致看了下这三个方法,proxyOrLoad,lockAndLoad这两人都有视情况不同而调用load方法.这样就先研究这个load方法了.
今天写了不少,虽说是有些乱.在下一篇中将重点看这个load方法.
评论
1, "那两种getEntityPersister有什么区别?" 现在感觉第一种方式包含在第二种里了, 我们做下的猜想: 第二种通过EntityClassName从那个factory中以Map的key方式取出EntityPersister, 也就是说比第一种多了个map的get()操作.2, "新类EntityKey,不禁要问这个类是干啥的?" 回过头来看, 觉得这个类是当把load来的东西放到缓存时的Key.
说是放到缓存时的Key不够确切, 应该说是放到当前Session缓存中的Key, 与二级缓存没关系, 想想也是二级缓存是Hibernate的调用者选择配置的, Hibernate自身怎么回"干涉"二级缓存中的事呢?
现在感觉第一种方式包含在第二种里了, 我们做下的猜想: 第二种通过EntityClassName从那个factory中以Map的key方式取出EntityPersister, 也就是说比第一种多了个map的get()操作.
2, "新类EntityKey,不禁要问这个类是干啥的?"
回过头来看, 觉得这个类是当把load来的东西放到缓存时的Key.
不仅仅是一个自己项目中那样的NullPointerException问题,这时还包括在那种情况下都没有得到实例的情况,hibernate已经通过if... else把漏网之鱼堵住了,本质上跟自己项目中的情况大不一样.
发表评论
-
createSQLQuery时,addScalar的应用
2010-11-19 16:11 2676问题起因: 抛了异常:n ... -
Hibernate源码研究碎得整理(14-25)
2010-10-24 19:30 27591, Hibernate源码研究碎得(十四): EntityK ... -
Hibernate:Query中list、iterate和uniqueResult三个方法的区别
2010-09-07 16:31 3647想看下org.hibernate.Query接口中定义的三 ... -
Hibernate如何实现分页的?
2009-12-17 14:50 4840解决项目中一问题时, 由于涉及到Hibernate的分 ... -
Hibernate删除一个session.load来的Model类?
2009-11-27 16:44 1568如下所示: public stati ... -
关于Session.getIdentifier(Object entity)的讨论
2009-08-10 17:30 1966在重读Hibernate时,在4.2.2一节发现这么一段话: ... -
Hibernate(25): Eclipse的debug欺骗了我
2009-05-08 09:45 1879Hibernate(24): 为什 ... -
Hibernate(24): 为什么用DetachedCriteria不能表连接地取数据?
2009-05-05 08:39 3339HQL到DetachedCriteria的转换? 中 ... -
Hibernate(23):一个较为复杂些的例子
2009-04-27 08:55 1905觉得该用一个更加丰富的例子来进一步研究Hibernat ... -
Hibernate(22):openSession的执行细节及相对优势
2009-04-23 11:04 2848Hibernate(21):getCurrentSession ... -
Hibernate(21):getCurrentSession还是用openSession?
2009-04-22 09:48 4545从Hibernate(十九): ... -
Hibernate(20):默认情况下决定commit时session命运的三个条件
2009-04-21 10:03 2888Hibernate(十九): 异 ... -
Hibernate(十九): 异常"Session was already closed"
2009-04-20 08:33 9094做一个Hibernate简单实验时, 碰到了这个异 ... -
Hibernate(十八): Hibernate初始化时如何生成SQL语句?
2009-04-13 09:24 5362昨天看Hibernate方面书时又看到了"d ... -
Hibernate(十七): Criteria子查询与ENTITY_MAP时的问题(续一)
2009-04-09 08:39 2368在Hibernate(十六): DetachedCri ... -
Hibernate(十六): DetachedCriteria子查询与ALIAS_TO_ENTITY
2009-04-08 13:01 8836跟Hibernate(十五):用Hibernate求记 ... -
Hibernate(十五):用Hibernate求记录总数的一个怪胎
2009-04-07 21:28 4223项目中求满足某一条件记录数是这样来的: super. ... -
怎么用Hibernate中的Criteria来表达下面的SQL
2009-02-24 16:07 1898这个问题解决 后, 我对Hibernate的查询功能更感兴趣了 ... -
Hibernate源码研究碎得(十四): EntityKey类的作用及研究方法收获
2009-02-22 22:43 2200在博客"http://rmn190.iteye ... -
Hibernate源码研究碎得整理(一到十三)
2009-02-21 16:32 5979前段时间对Acegi的研究,又勾起我当时看Hibern ...
相关推荐
本篇文章将详细解析Hibernate中的三种主要查询方式——HQL(Hibernate Query Language)、Criteria API和Query API,并着重讨论`load()`与`get()`方法的区别。 一、HQL查询 Hibernate Query Language(HQL)是...
在Java的持久化框架Hibernate中,`get`和`load`方法都是用于从数据库中获取对象,但它们之间存在一些重要的区别。理解这些差异对于优化应用程序的性能和避免潜在问题至关重要。 首先,`get`方法是直接从数据库中...
在Hibernate源码中,`get`方法直接调用了`sessionFactory`的`load`方法,但是传递了一个额外的参数`LockMode.NONE`,这表明它不希望获取任何锁定。而`load`方法允许设置不同的锁模式,以支持并发控制。 在实际开发...
`load`和`get`方法是Hibernate中用于检索实体的两种主要方式,它们都是从Session接口中调用,但有明显的区别和各自的适用场景。 1. `load`方法: - `load`方法主要用于根据主键加载对象,它返回一个代理对象,而...
5. **Session接口**:是Hibernate的核心接口,负责对象的持久化操作,如保存(save())、更新(update())、删除(delete())以及查询(load(), get())等。 6. **Transaction管理**:Hibernate支持JTA(Java ...
Hibernate 是一个著名的开源Java对象关系映射(ORM)框架,它极大地简化了数据库与Java应用程序之间的交互。在本文中,我们将深入探讨Hibernate 3.6.1版本的源码,了解其内部工作原理以及关键组件的功能。 源码分析...
2. **持久化模型**:源码中可以看到,Hibernate通过注解或XML配置文件来定义Java类为持久化实体,实现了对象与数据库表之间的映射。 3. **缓存机制**:Hibernate支持二级缓存,源码中可以深入理解其工作流程,包括...
**hibernate入门学习笔记+源码** **一、Hibernate简介** Hibernate是一个开源的对象关系映射(ORM)框架,它简化了Java应用与数据库之间的交互。通过提供对象化的数据访问方式,Hibernate消除了传统JDBC代码中的...
4. 加载(Load/Get):根据主键从数据库中获取对象,返回持久化状态的对象。 六、查询语言 1. HQL:Hibernate查询语言,类似SQL但面向对象,可以方便地进行对象间的关联查询。 2. Criteria API:提供更灵活的查询...
在深入探讨Hibernate源码之前,我们首先需要理解什么是对象持久化技术。对象持久化是将内存中的对象状态保存到持久存储介质(如数据库)中,以便在后续的程序运行中可以恢复这些对象的状态。它解决了应用程序中的...
《Hibernate源码解析(一)》 在Java开发领域,Hibernate作为一款强大的对象关系映射(ORM)框架,极大地简化了数据库操作。深入理解Hibernate的源码,不仅可以帮助开发者更好地运用该工具,还能提升对Java编程和...
在Hibernate源码的学习过程中,我们可以深入理解ORM的工作原理,提高我们的Java开发技能,并且能够更好地优化数据库操作。 一、Hibernate核心组件 1. Configuration:配置对象,负责读取hibernate.cfg.xml文件,...
【hibernate_first_new项目源码】是一个关于Hibernate框架学习的项目,主要涵盖了对Hibernate常用接口的详细讲解和实例应用。Hibernate是一个强大的Java持久层框架,它为开发者提供了对象关系映射(ORM)功能,使得...
本资源“Hibernate基础学习源码”提供了五个不同阶段的学习示例,分别命名为Hibernate_01至Hibernate_04以及Hibernate_M2M,涵盖了Hibernate的基本概念、配置、实体映射、CRUD操作以及多对多关系的处理。 1. **...
《Hibernate电子版及源码》资源集合是一份珍贵的学习材料,专为那些渴望深入了解Java持久化框架Hibernate的开发者准备。Hibernate作为一个开源的对象关系映射(ORM)框架,它极大地简化了Java应用程序对数据库的操作...
传智播客李勇hibernate源码1-20课,目录如下:01_hibernate介绍与动手入门体验;02_hibernate入门案例的细节分析; 03_hibernate入门案例的代码优化; 04_Session接口及get|load|persist方法 05_实体对象的三种状态...
这份资料包含的中文说明将帮助开发者更好地理解和使用Hibernate3.2,而源码则提供了深入学习和研究的宝贵资源。 1. Hibernate ORM概述: Hibernate是一种将Java对象与关系数据库进行映射的技术,它通过提供一种...
Hibernate是一个开源的对象关系映射(ORM)框架,它允许Java开发者将数据库操作转换为对象级别的操作,从而简化了数据访问层的开发。在 Hibernate 3.2 版本中,这个框架已经相当成熟,提供了丰富的功能和性能优化。...
2. **实体类和映射文件**:在Hibernate中,我们创建Java类来表示数据库中的表,通过Hibernate的XML映射文件(或注解)定义这些类与数据库表的对应关系。 3. **SessionFactory和Session**:SessionFactory是...
Java Hibernate 是一个强大的持久化框架,它简化了Java应用程序与关系数据库之间的交互。这个"java hibernate 上课源码6"应该包含了一系列示例代码,用于教授如何在实际项目中应用Hibernate。通过深入理解这些源码,...