Hibernate源码分析杂记

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

最近在看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

目录
相关文章
|
SQL 缓存 Java
框架分析(9)-Hibernate
框架分析(9)-Hibernate
|
10月前
|
缓存 Java 数据库连接
Hibernate:Java持久层框架的高效应用
通过上述步骤,可以在Java项目中高效应用Hibernate框架,实现对关系数据库的透明持久化管理。Hibernate提供的强大功能和灵活配置,使得开发者能够专注于业务逻辑的实现,而不必过多关注底层数据库操作。
113 1
|
SQL Java 数据库连接
Hibernate 是一款开源 ORM(对象关系映射)框架,封装了 JDBC,允许以面向对象的方式操作数据库,简化了数据访问层的开发。
Hibernate 是一款开源 ORM(对象关系映射)框架,封装了 JDBC,允许以面向对象的方式操作数据库,简化了数据访问层的开发。通过映射机制,它可以自动处理对象与数据库表之间的转换,支持主流数据库,提高了代码的可移植性和可维护性。其核心接口包括 SessionFactory、Session 和 Transaction 等,通过它们可以执行数据库的 CRUD 操作。配置方面,需在项目中引入 Hibernate 及数据库驱动依赖,并创建 `hibernate.cfg.xml` 配置文件来设置数据库连接和 Hibernate 行为参数。
158 1
|
数据库 Java 数据库连接
Struts 2 与 Hibernate 的完美邂逅:如何无缝集成两大框架,轻松玩转高效 CRUD 操作?
【8月更文挑战第31天】本文通过具体示例介绍了如何在 Struts 2 中整合 Hibernate,实现基本的 CRUD 操作。首先创建 Maven 项目并添加相关依赖,接着配置 Hibernate 并定义实体类及其映射文件。然后创建 DAO 接口及实现类处理数据库操作,再通过 Struts 2 的 Action 类处理用户请求。最后配置 `struts.xml` 文件并创建 JSP 页面展示用户列表及编辑表单。此示例展示了如何配置和使用这两个框架,使代码更加模块化和可维护。
374 0
|
SQL XML 存储
Hibernate框架【五】——基本映射——多对多映射
Hibernate框架【五】——基本映射——多对多映射
289 0
|
Java 数据库连接 数据库
探索JPA生态:Hibernate与其他ORM框架的对比分析
【6月更文挑战第25天】**JPA标准下的Hibernate是流行的ORM实现,提供丰富功能如二级缓存和延迟加载,但其学习曲线较陡,性能优化复杂。相比如MyBatis,Hibernate的JPQL更面向对象,MyBatis则接近SQL。选择ORM需考虑项目需求和个人偏好。**
201 0
|
Java 数据库连接
杨老师课堂之JavaEE三大框架Hibernate入门第一课
杨老师课堂之JavaEE三大框架Hibernate入门第一课
85 0
|
SQL Java 数据库连接
Java从入门到精通:3.1.2深入学习Java EE技术——Hibernate与MyBatis等ORM框架的掌握
Java从入门到精通:3.1.2深入学习Java EE技术——Hibernate与MyBatis等ORM框架的掌握
164 1