`

从源码层面来看load与get的区别(三): Hibernate源码研究碎得(7)

阅读更多

LoadEventListener中的LoadType


接着上一篇,我们来看方法fireLoad(event, LoadEventListener.GET);
第一个参数就是前面已经准备好的LoadEvent对象,我们重点看下第二个参数.
这个fireLoad的签名是这样的:
 fireLoad(LoadEvent event, LoadType loadType)

追着看下LoadType的定义,有点吓一跳,这个类是在接口LoadEventListener中定义的一个static final类型的Class,这还真是第一次见,以前见过在普通类中定义或static或非static内部类的,一真没见过这样在接口中定义的.写动这里,有一个疑问在接口中可不可以定义一个非static也非final的类呢?当在Eclipse里写了如下的定义并保存时,Eclipse没有报错.
 public interface MyInterface {
  public class MyInnerClass{
  
  }
 }
Eclipse没有报错,说明这样的定义是可以的.但又禁不住多想了一下:在接口中声明属性时,编译器都会自动地给加上"public static final"来修饰的,那我在定义MyInnerClass时即使没有显式地写上"static final",编译器在编译时也会不会自动回呢? ------------- 这个问题先放这,毕竟与Hibernate有些远了,等看了相关的说明再做解释.

言归正转.
先围绕着这个LoadType里的属性往前多想一下.LoadType里有如下五个属性:
 String类型的name,其余四个都是boolean类型的,依次是nakeEntityReturned,allowNulls,checkDeleted,allowProxyCreation.这四个boolean型的属性会在以后有什么用呢?nakeEntityReturned是否与allowProxyCreation有点重复?总觉得在Hibernate里只要不允许创建Proxy就是nake的了.还有这个allowNulls,这里的null是指什么?是指要load里来的对象属性是否为空(也就是是否延时加载)?还是指这个要加载的对象是否可为Proxy?这样一来又与那两allowProxyCreation的定义有冗余了.这个checkDeleted是check什么的deleted与否?这些问题的进一步澄清还得依赖以后对Hibernate更多的了解与具体应用中的细心体会,不过现在这样一想,最起码的好处是记住了LoadType里有这么四个boolean的属性.

LoadEventListener里定义了这个LoadType类后又在LoadEventListener接口中定义了几个LoadType的常量(当然是public static final的了),依次是RELOAD,GET,LOAD,IMMEDIATE_LOAD,INTERNAL_LOAD_EAGER,INTERNAL_LOAD_LAZY和INTERNAL_LOAD_NULLABLE.

值得注意的是如下两点:
 1,这里的RELOAD和GET,它们的name都是"GET",所不同的另外的四个属性不同,那为什么要起相同的name呢?这里面又有什么玄机?
 2,比较LOAD和GET,发现它们的allowProxyCreation属性相反:GET里为false,LOAD里为true,是否这就是为什么Session里get方法返回是实打实地从数据库里取出的数据而load只是返回一个proxy对象的根源所在?这个问题先放在这等对get和load方法比较的差不多时再回过头解释.
 对LoadEventListener下的LoadType花了点时间后,下面进入fireLoad方法本身.

 前两句调用errorIfClosed();checkTransactionSynchStatus();第一个方法可能抛出SessionException异常,即throw new SessionException( "Session is closed!" );这个异常可是很常见的终于知道是怎么抛出了,呵呵...第二个方法再深追就很长了,现在也不大清楚是干啥的,就先放在这.

 接着往下走,从已注册的listeners中getLoadEventListeners,再通过for循环的方式依次调用LoadEventListener的onLoad,这个onLoad方法的形参也就是前面准备好的event和loadType了.

 接下来进入LoadEventListener接口的实现类DefaultLoadEventListener执行onLoad方法,这样get方法就将进入实质性的执行阶段.
  
 DefaultLoadEventListener中的onLoad方法的实现很长,有五十多行,只能在下一篇里详细研究了,本篇里先简单看下DefaultLoadEventListener这个类.
 
 很好奇这个类里先定义了两个static final修饰的Object类型对象,分别命名为REMOVED_ENTITY_MARKER和INCONSISTENT_RTN_CLASS_MARKER.以前可是没见过直接new一个Object类型对象的,在Hibernate这可真是开眼了.这两个Object对象有什么用?又怎么用呢?毕竟Object里实在没有什么可以拿的出手的方法.
 在DefaultLoadEventListener里搜了下后发现return语句后用到了这两个对象,那这样也就是说用Object对象来指向get到的数据了?那怎么能放到Object对象里面呢?Object本身又没有什么专门的方法,再说这两个Object对象已定义为final也就不会再利用"父类变量来指向子类实例"这一特性了. 再细看DefaultLoadEventListener类里对这两个方法的应用,也就是如下的语句:
 if ( entity == REMOVED_ENTITY_MARKER ) {
    log.debug( "load request found matching entity in context, but it is scheduled for removal;       returning null" );
   return null;
 }

 这两Object的作用还真是与它的名字所言,就是作为Marker来用的.那为什么不像平常所见的所样定义个int类型的常量呢?噢,若这样的话与那个entity就没法比较了,不对呀,Java里不是对那些基本类型都有了封装类了吗?那基本类型的封装是在1.5中才有的,为了兼容在Hibernate里没用这个新特性?这样的解释能说的通吗?  --- 这个离Hibernate远一点的问题就先放在这,以后再回过头来看吧.
 
 DefaultLoadEventListener类中还有一个属性:LockMode DEFAULT_LOCK_MODE = LockMode.NONE;这个是要干啥用的?搜了下本类中没有用到,再说那个LoadEvent里已有这个属性了,是要与LoadEvent里的那个属性比较?比较的话也不至于再在这声明一个DEFAULT_LOCK_MODE引用,NONE本身是一个static final修饰的,直接要来用就OK了, ... 不对,这里有点东西,NONE是一个static final的没错,不过在这LockMode.NONE这么一声明就相当于又new了一个LockMode对象,可放在这又有什么用呢?  --- 先放一放.

 DefaultLoadEventListener类中除了onLoad这个接口实现方法外还有十个或private或protected的方法,都是直接或间接地被onLoad调用的,在下一篇中结合onLoad方法再细细研究.

 

2
1
分享到:
评论
1 楼 rmn190 2009-02-21  
INCONSISTENT_RTN_CLASS_MARKER 和 REMOVED_ENTITY_MARKER怎么用?

1, 他们都是一个Object类的实例,从其封装的属性来看,没有任何区分, 这样就只能通过它们在内存中的地址来区分了. 结合当前类里的loadFromSessionCache方法看,明白了.

2, 但为什么不用字符串呢? 用字符串比较时要比直接比较内存地址慢? 可能是这个原因吧.

相关推荐

    hibernate 三种 查询 方式 load与get的区别

    NULL 博文链接:https://cici9898-007.iteye.com/blog/1847710

    hibernate中get和load方法的区别

    NULL 博文链接:https://ysj5125094.iteye.com/blog/1897557

    传智播客李勇hibernate源码1-20课

    传智播客李勇hibernate源码1-20课,目录如下:01_hibernate介绍与动手入门体验;02_hibernate入门案例的细节分析; 03_hibernate入门案例的代码优化; 04_Session接口及get|load|persist方法 05_实体对象的三种状态...

    Hibernate的get和load方法的区别

    NULL 博文链接:https://811417208-qq-com.iteye.com/blog/506950

    Hibernate查询 load与get的区别及其它查询测试

    NULL 博文链接:https://quicker.iteye.com/blog/658451

    hibernate get/load/saveOrUpdate/statistics

    博文链接:https://log-cd.iteye.com/blog/205166

    spring_MVC源码

    15. <load-on-startup>1</load-on-startup> 16. </servlet> 17. <servlet-mapping> 18. <servlet-name>spring</servlet-name> <!-- 这里在配成spring,下边也要写一个名为spring-servlet.xml的文件,主要用来...

    ssh(structs,spring,hibernate)框架中的上传下载

     需要指定的是Spring 1.2.5提供了两套Hibernate的支持包,其中Hibernate 2相关的封装类位于org.springframework.orm.hibernate2.*包中,而Hibernate 3.0的封装类位于org.springframework.orm.hibernate3.*包中,...

    DWR.xml配置文件说明书(含源码)

    因为指定属性转换只有针对bean才有效(基本类型的转换没有必要指定属性),这个功能只能应用与特定的converter即BeanConverter和从次类派生的所有类.相关配置语法如下 , property2"/> 这样就可以限定DWR不能调用Fred...

    cms后台管理

    解压缩jeecms-3.0.2-final-src,在src文件夹下会看到有三个压缩文件,如果只想进行普通的二次开发,可以只导入cms这个源码,删除jeecms-cms-identity-3.0.2-final.jar即可,如果想进行深入的二次开发,需要导入...

    springmybatis

    mybatis实战教程mybatis in action之五与spring3集成附源码 mybatis实战教程mybatis in action之六与Spring MVC 的集成 mybatis实战教程mybatis in action之七实现mybatis分页源码下载 mybatis实战教程mybatis in ...

Global site tag (gtag.js) - Google Analytics