Hibernate源码分析杂记

最近在看hibernate在load entity过程中的操作, 包括为实体类做增强,自动flush,一级缓存,在这里记录一下,慢慢会继续更新。

 

DefaultLoadEventListener:

final PersistenceContext persistenceContext = event.getSession().getPersistenceContext();

StatefulPersistenceContext.proxiesByKey 缓存实体

 

DefaultLoadEventListener:

private Object createProxyIfNecessary(
Object proxy = persister.createProxy( event.getEntityId(), event.getSession() );
		persistenceContext.getBatchFetchQueue().addBatchLoadableEntityKey( keyToLoad );
		persistenceContext.addProxy( keyToLoad, proxy );

 

 

EventListenerRegistryImpl 注册所有listener, 

private Map<EventType,EventListenerGroupImpl> registeredEventListenersMap = prepareListenerMap();

 

prepareListenerMap初始化需要的listener,调用prepareListeners完成实际动作。

prepareListeners(
				PRE_COLLECTION_UPDATE,
				workMap
		);

 

 

EventType与lisnter接口类对应,保存了event对应的实际处理的lisnter类。 

private EventType(String eventName, Class<? extends T> baseListenerInterface) {
		this.eventName = eventName;
		this.baseListenerInterface = baseListenerInterface;
	}

 

 

本身用static方式初始化了eventype对应的listener。

public static final EventType<MergeEventListener> MERGE
			= new EventType<MergeEventListener>( "merge", MergeEventListener.class );

 

 

Listener处理实际的event,以DefaultAutoFlushEventListener为例,该listener接收到AutoFlushEvent, 会查找该event内关联的session(用session接口的子接口EventSource),session的实现类是SessionImpl,其声明如下

public final class SessionImpl extends AbstractSessionImpl implements EventSource

 

DefaultAutoFlushEventListener的方法onAutoFlush(AutoFlushEvent event) 对event的处理如下:

final int oldSize = source.getActionQueue().numberOfCollectionRemovals();
			flushEverythingToExecutions(event);
			if ( flushIsReallyNeeded(event, source) ) {
				LOG.trace( "Need to execute flush" );

				performExecutions(source);
				postFlush(source);
				// note: performExecutions() clears all collectionXxxxtion
				// collections (the collection actions) in the session

				if ( source.getFactory().getStatistics().isStatisticsEnabled() ) {
					source.getFactory().getStatisticsImplementor().flush();
				}
			}

 

 

performExecutions中有如下调用,可以看到其根据session中保存的actionQueue进行处理,对action顺序进行重排:

session.getActionQueue().prepareActions();

session.getActionQueue().executeActions();

 

prepareAction调用保存的action的beforeExecutions方法,对action进行预处理

public void prepareActions() throws HibernateException {
		prepareActions( collectionRemovals );
		prepareActions( collectionUpdates );
		prepareActions( collectionCreations );
		prepareActions( collectionQueuedOps );
	}

 

executeActions则按顺序执行保存的action,实际调用的是action的execute方法:

	public void executeActions() throws HibernateException {
		if ( ! unresolvedInsertions.isEmpty() ) {
			throw new IllegalStateException(
					"About to execute actions, but there are unresolved entity insert actions."
			);
		}
		executeActions( insertions );
		executeActions( updates );
		// do before actions are handled in the other collection queues
		executeActions( collectionQueuedOps );
		executeActions( collectionRemovals );
		executeActions( collectionUpdates );
		executeActions( collectionCreations );
		executeActions( deletions );
	}

 

 

各种CRUD的action都实现了Executable的接口,该接口主要定义了execute()和beforeExecutions()方法,用于执行action前的一些处理操作和之后的实际操作。

action的一些继承层次如下:

public final class EntityInsertAction extends AbstractEntityInsertAction

public abstract class AbstractEntityInsertAction extends EntityAction

public abstract class EntityAction

implements Executable, Serializable, Comparable, AfterTransactionCompletionProcess

 

 

performExecutions(EventSource session) 中有这么一句:

session.getTransactionCoordinator().getJdbcCoordinator().flushEnding();

 

实现类是TransactionCoordinatorImpl, 其构造函数中:

this.jdbcCoordinator = new JdbcCoordinatorImpl( userSuppliedConnection, this );
this.transactionEnvironment = transactionContext.getTransactionEnvironment();

 

 

flushEnding中涉及到一个flushDepth,主要处理可能产生多个begin调用,每个begin调用都会让这个depth数量+1, 保证最后的end处理同样数量的flush.

	public void flushEnding() {
		flushDepth--;
		if ( flushDepth < 0 ) {
			throw new HibernateException( "Mismatched flush handling" );
		}
		if ( flushDepth == 0 ) {
			releasesEnabled = true;
		}

		afterStatementExecution();
	}

 

 

一个查询的处理流程:

Servlet.processRequest->JdbcTransaction.beforeTransactionCommit->SessionImpl.managedFlush->SessinImpl.flush->DefaultFlushEventListener.onFlush

->AbstractFlushingEventListener.performExecutior->JdbcCoordinatorImpl.flushEnding

时间: 2024-09-22 21:57:10

Hibernate源码分析杂记的相关文章

《深入理解SPARK:核心思想与源码分析》一书正式出版上市

自己牺牲了7个月的周末和下班空闲时间,通过研究Spark源码和原理,总结整理的<深入理解Spark:核心思想与源码分析>一书现在已经正式出版上市,目前亚马逊.京东.当当.天猫等网站均有销售,欢迎感兴趣的同学购买.我开始研究源码时的Spark版本是1.2.0,经过7个多月的研究和出版社近4个月的流程,Spark自身的版本迭代也很快,如今最新已经是1.6.0.目前市面上另外2本源码研究的Spark书籍的版本分别是0.9.0版本和1.2.0版本,看来这些书的作者都与我一样,遇到了这种问题.由于研究和

深入理解Spark:核心思想与源码分析

大数据技术丛书 深入理解Spark:核心思想与源码分析 耿嘉安 著 图书在版编目(CIP)数据 深入理解Spark:核心思想与源码分析/耿嘉安著. -北京:机械工业出版社,2015.12 (大数据技术丛书) ISBN 978-7-111-52234-8 I. 深- II.耿- III.数据处理软件 IV. TP274 中国版本图书馆CIP数据核字(2015)第280808号 深入理解Spark:核心思想与源码分析 出版发行:机械工业出版社(北京市西城区百万庄大街22号 邮政编码:100037)

Spring事务源码分析(一)Spring事务入门

有时为了保证一些操作要么都成功,要么都失败,这就需要事务来保证.  传统的jdbc事务如下:  ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 @Test     public void testAdd(){         Connection con=null;         try {             con=DriverManager.getConnection(url , username

深入理解Spark:核心思想与源码分析. 导读

  大数据技术丛书   深入理解Spark:核心思想与源码分析 耿嘉安 著     Preface  前言 为什么写这本书 要回答这个问题,需要从我个人的经历说起.说来惭愧,我第一次接触计算机是在高三.当时跟大家一起去网吧玩CS,跟身边的同学学怎么"玩".正是通过这种"玩"的过程,让我了解到计算机并没有那么神秘,它也只是台机器,用起来似乎并不比打开电视机费劲多少.高考填志愿的时候,凭着直觉"糊里糊涂"就选择了计算机专业.等到真正学习计算机课程的时

WebWork2源码分析

web Author: zhuam   昨晚一口气看完了夏昕写的<<Webwork2_Guide>>,虽然文档资料很简洁,但仍不失为一本好的WebWork2书籍,看的出作者的经验和能力都是非常的老道,在此向作者的开源精神致敬,并在此引用夏昕的那句话So many open source projects, Why not Open your Documents?   今天下载了最新的WebWork2版本, 开始了源码分析,这份文档只能算是我的个人笔记,也没时间细细校对,且个人能力有

JUnir源码分析(一)

一.引子 JUnit源码是我仔细阅读过的第一个开源项目源码.阅读高手写的代码能学到一些好的编程风格和实现思路,这是提高自己编程水平行之有效的方法,因此早就想看看这些赫赫有名的框架是怎么回事了.今天就拿最简单的JUnit下手,也算开始自己的源码分析之路.   JUnit作为最著名的单元测试框架,由两位业界有名人士协力完成,已经经历了多次版本升级(了解JUnit基础.JUnit实践).JUnit总体来说短小而精悍,有不少值得我们借鉴的经验在里面:但是也有一些不足存在,当然这对于任何程序来说都是难免的

java io学习(三) 管道的简介,源码分析和示例

管道(PipedOutputStream和PipedInputStream)的简介,源码分析和示例 本章,我们对java 管道进行学习. java 管道介绍 在java中,PipedOutputStream和PipedInputStream分别是管道输出流和管道输入流. 它们的作用是让多线程可以通过管道进行线程间的通讯.在使用管道通信时,必须将PipedOutputStream和PipedInputStream配套使用. 使用管道通信时,大致的流程是:我们在线程A中向PipedOutputStr

java io学习(二)ByteArrayOutputStream的简介,源码分析和示例

ByteArrayOutputStream的简介,源码分析和示例(包括OutputStream) 前面学习ByteArrayInputStream,了解了"输入流".接下来,我们学习与ByteArrayInputStream相对应的输出流,即ByteArrayOutputStream. 本章,我们会先对ByteArrayOutputStream进行介绍,在了解了它的源码之后,再通过示例来掌握如何使用它. ByteArrayOutputStream 介绍 ByteArrayOutputS

java io学习(一)ByteArrayInputStream的简介,源码分析和示例

ByteArrayInputStream的简介,源码分析和示例(包括InputStream) 我们以ByteArrayInputStream,拉开对字节类型的"输入流"的学习序幕. 本章,我们会先对ByteArrayInputStream进行介绍,然后深入了解一下它的源码,最后通过示例来掌握它的用法. ByteArrayInputStream 介绍 ByteArrayInputStream 是字节数组输入流.它继承于InputStream. 它包含一个内部缓冲区,该缓冲区包含从流中读取