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