`

hibernate get load 源码分析

阅读更多

1 hibernate get 主要源码:

   

public Object get(String entityName, Serializable id) throws HibernateException {
		LoadEvent event = new LoadEvent(id, entityName, false, this);
		boolean success = false;
		try {
			fireLoad(event, LoadEventListener.GET);
			success = true;
			return event.getResult();
		}
		finally {
			afterOperation(success);
		}
	}

  

   load源码:

   

public Object load(String entityName, Serializable id) throws HibernateException {
		LoadEvent event = new LoadEvent(id, entityName, false, this);
		boolean success = false;
		try {
			fireLoad( event, LoadEventListener.LOAD );
			if ( event.getResult() == null ) {
				getFactory().getEntityNotFoundDelegate().handleEntityNotFound( entityName, id );
			}
			success = true;
			return event.getResult();
		}
		finally {
			afterOperation(success);
		}
	}

  

    由上可知:hibernate的get和load的加载上前半部分调用方法基本差不多,只是加载类型不一致,一个是get,一个是load;

    两种方式同样调用了fireLoad方法,在fireLoad里两者处理相同,都是调用了load事件对应的listener,调用listener的onLoad()方法,

    onLoad方法又会调用proxyOrLoad()方法,在proxyOrLoad方法上出现了差异:

    

			Object proxy = persistenceContext.getProxy(keyToLoad);
			if ( proxy != null ) {
				return returnNarrowedProxy( event, persister, keyToLoad, options, persistenceContext, proxy );
			}
			else {
				if ( options.isAllowProxyCreation() ) {//分支1 
					return createProxyIfNecessary( event, persister, keyToLoad, options, persistenceContext );
				}
				else {//分支2
					// return a newly loaded object
					return load(event, persister, keyToLoad, options);
				}
			}

    看了如上代码,在看看LoadEventListener.GET和LoadEventListener.LOAD的区别

    

public static final LoadType GET = new LoadType("GET")
			.setAllowNulls(true)//允许为空
			.setAllowProxyCreation(false)//不允许创建代理对象
			.setCheckDeleted(true)
			.setNakedEntityReturned(false);
	
	public static final LoadType LOAD = new LoadType("LOAD")
			.setAllowNulls(false)//允许为空
			.setAllowProxyCreation(true)//不允许创建代理对象
			.setCheckDeleted(true)
			.setNakedEntityReturned(false);

   get方式允许为空,不允许创建代理对象;load恰恰相反不允许为空,允许创建代理对象

  

   所以在方法proxyOrLoad()里load会走分支1,get会走分支2

 

    分支1 :get的实际操作在此:

	protected Object doLoad(
			final LoadEvent event,
			final EntityPersister persister,
			final EntityKey keyToLoad,
			final LoadEventListener.LoadType options) {

		if ( log.isTraceEnabled() ) {
			log.trace(
					"attempting to resolve: " +
					MessageHelper.infoString( persister, event.getEntityId(), event.getSession().getFactory() )
				);
		}

		Object entity = loadFromSessionCache( event, keyToLoad, options );
		if ( entity == REMOVED_ENTITY_MARKER ) {
			log.debug( "load request found matching entity in context, but it is scheduled for removal; returning null" );
			return null;
		}
		if ( entity == INCONSISTENT_RTN_CLASS_MARKER ) {
			log.debug( "load request found matching entity in context, but the matched entity was of an inconsistent return type; returning null" );
			return null;
		}
		if ( entity != null ) {
			if ( log.isTraceEnabled() ) {
				log.trace(
						"resolved object in session cache: " +
						MessageHelper.infoString( persister, event.getEntityId(), event.getSession().getFactory()  )
					);
			}
			return entity;
		}

		entity = loadFromSecondLevelCache(event, persister, options);
		if ( entity != null ) {
			if ( log.isTraceEnabled() ) {
				log.trace(
						"resolved object in second-level cache: " +
						MessageHelper.infoString( persister, event.getEntityId(), event.getSession().getFactory() )
					);
			}
			return entity;
		}

		if ( log.isTraceEnabled() ) {
			log.trace(
					"object not resolved in any cache: " +
					MessageHelper.infoString( persister, event.getEntityId(), event.getSession().getFactory() )
				);
		}

		return loadFromDatasource(event, persister, keyToLoad, options);
	}

   由上可见:get先去一级缓存里去查找是否存在要返回的对象,如果不存在,则去二级缓存里查找,如果没有则从数据库中加载。

 

   分支2:load加载数据方式:

   

		Object existing = persistenceContext.getEntity( keyToLoad );
		if ( existing != null ) {
			// return existing object or initialized proxy (unless deleted)
			log.trace( "entity found in session cache" );
			if ( options.isCheckDeleted() ) {
				EntityEntry entry = persistenceContext.getEntry( existing );
				Status status = entry.getStatus();
				if ( status == Status.DELETED || status == Status.GONE ) {
					return null;
				}
			}
			return existing;
		}
		else {
			log.trace( "creating new proxy for entity" );
			// return new uninitialized proxy
			Object proxy = persister.createProxy( event.getEntityId(), event.getSession() );
			persistenceContext.getBatchFetchQueue().addBatchLoadableEntityKey(keyToLoad);
			persistenceContext.addProxy(keyToLoad, proxy);
			return proxy;
		}

    load首先会去缓存里查找,否则则创建代理对象(load的代理对象在获取对象属性时究竟如何加载数据?在以后的分析中再做详细分析)

 

   

分享到:
评论

相关推荐

    Hibernate源码解析(一)

    - 错误排查:当遇到问题时,源码分析能更准确地定位问题所在,提高解决问题的效率。 - 自定义扩展:熟悉源码后,我们可以根据需求自定义拦截器、事件监听器等,实现特定功能。 总结来说,Hibernate源码解析是一个...

    hibernate-3.2源码包

    5. **Session接口**:是Hibernate的核心接口,负责对象的持久化操作,如保存(save())、更新(update())、删除(delete())以及查询(load(), get())等。 6. **Transaction管理**:Hibernate支持JTA(Java ...

    hibernate-3.2 源码

    通过阅读和分析Hibernate 3.2的源码,我们可以深入了解ORM框架的设计理念,学习如何优化数据库操作,以及如何在实际项目中灵活运用Hibernate提供的各种功能。同时,这也有助于我们掌握Java反射、代理、元数据解析等...

    hibernate3.6.1源码

    源码分析: 1. **对象关系映射(ORM)**:Hibernate的核心功能是实现ORM,它将Java类映射到数据库表,对象的属性对应于表的列。在Hibernate 3.6.1中,这一映射主要通过`hibernate.cfg.xml`配置文件和`.hbm.xml`映射...

    hibernate5jar包以及源码

    5. **CRUD操作**:通过Session的save、update、delete、get和load方法进行创建、读取、更新和删除操作。 6. **查询**:使用HQL或Criteria API进行复杂查询,如分页、条件筛选等。 **四、实战应用** 1. **事务管理**...

    圣思园Hibernate课件、源码

    7. 源码分析:通过阅读和理解源码,加深对Hibernate内部工作原理的认识,如对象状态管理、持久化机制等。 8. 实战项目:结合实例,将学到的知识应用到实际项目中,例如构建一个简单的Web应用,实现数据的持久化操作...

    hibernate入门学习笔记+源码

    **六、源码分析** `hibernate_test`、`hibernate_test3`、`hibernate_test2`这些文件可能包含了示例项目的源代码,包括配置文件、实体类、DAO层操作以及测试用例。通过分析这些源码,你可以更好地理解Hibernate在...

    hibernate源码的学习

    3.托管状态:对象已由Session的load()或get()方法加载,或通过事务提交后的瞬时对象。 4.脱管状态:Session关闭后,持久化对象变为脱管状态,其数据库连接断开。 三、实体映射 - @Entity表示一个Java类作为数据库表...

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

    04_Session接口及get|load|persist方法 05_实体对象的三种状态与saveOrUpdate方法 06_完善HibernateUtil类及hql查询入门 07_实体类或属性名与数据库关键字冲突问题 10_使用Hibernate完成CRUD实验的步骤说明 11_...

    java hibernate上课源码6

    这个"java hibernate 上课源码6"很可能包含了以上这些知识点的实例,通过分析和运行这些代码,你可以更好地理解和掌握Hibernate的使用。每个文件可能对应一个特定的主题,例如配置文件的设置、CRUD操作的实现、关联...

    HIbernate3.2中文说明及其源码

    Hibernate的源码分析对于深入理解其工作原理至关重要。通过阅读源码,可以了解如何实现对象的持久化、事务管理、缓存策略等核心功能。特别地,SessionFactory的创建过程、Session的生命周期管理以及查询机制的实现...

    Hibernate电子版及源码

    此外,源码分析有助于提升开发者对Java反射机制、动态代理以及JPA规范的理解。 Hibernate的核心特性包括: 1. 对象关系映射:Hibernate允许开发者将Java类与数据库表进行映射,通过对象的方式来操作数据,使得开发...

    java hibernate上课源码1

    Java Hibernate 是一个强大的对象关系映射(ORM)框架,它允许...通过分析和运行这些源码,你可以更直观地了解Hibernate的工作流程,加深对ORM框架的理解。记得结合理论知识和实际代码,逐步掌握Hibernate的精髓。

    hibernate入门源代码

    5. **持久化操作**: 使用Session的`save()`, `update()`, `delete()`, `load()`和`get()`等方法进行数据操作。 6. **查询数据**: 可以使用HQL(Hibernate Query Language)或Criteria API来执行查询。 7. **提交...

    hibernate源码

    源码分析是深入理解其工作原理的关键,以下将详细探讨Hibernate的核心概念、设计模式以及主要模块。 一、Hibernate 概述 Hibernate 提供了一种在Java应用中持久化对象的机制,它通过映射Java类到数据库表来实现。...

    SSH CRM 项目Hibernate操作数据字典源码(3)

    接下来,我们分析`Hibernate操作数据字典源码(3)`文档中的关键内容。在Hibernate中,数据字典对应的实体类会包含一系列属性,每个属性对应数据库表中的字段。例如,数据字典可能有一个实体类`Dictionary`,其中...

    HIBERNATE例题源码

    查询数据则通过`Session.get()`或`Session.load()`,或者使用`Criteria`或`HQL`(Hibernate查询语言)进行更复杂的查询;更新对象时调用`Session.update()`,而删除则使用`Session.delete()`。 在文件列表中,`...

    Hibernate一对一关系源码

    本主题聚焦于Hibernate中的一对一(OneToOne)关系的源码分析,这对于理解Hibernate的工作原理和优化数据访问性能至关重要。 在Hibernate中,一对一关系是指两个实体类之间存在一个唯一的对应关系,通常通过主键...

    7.1.1Hibernate的入门必备——文档和源码

    源码分析可以帮助深入理解Hibernate的工作原理,例如,查看Session是如何通过Criteria API或HQL执行查询的,以及如何处理事务。同时,实践操作,如搭建一个简单的示例项目,从创建数据库表到编写实体类,再到实现...

    黑马程序员_hibernate框架开发2016版讲义和笔记资料_day1_day2_day3_day4

    4.2 CRUD操作:通过Session的save()、update()、delete()和get()、load()方法实现对数据库的增删改查。 4.3 查询语言HQL:Hibernate Query Language是Hibernate提供的面向对象的查询语言,类似于SQL但更面向对象。 ...

Global site tag (gtag.js) - Google Analytics