本文主要通过源码,概述一下session的查询过程。
主要api有get、load。他们基本过程是类似的;
以get为例:
Session
public Object get(String entityName, Serializable id) throws HibernateException;
调用SessionImpl:
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);
}
}
fireLoad 主要是出发监听器;
主要获取过程就是 event.getResult();
event为LoadEvent,其实是一个很简单的类,其getResult也是非常简单,
public Object getResult() {
return result;
}
public void setResult(Object result) {
this.result = result;
}
其中result其实是由 fireLoad(event, LoadEventListener.GET) 执行过程中赋值的
private void fireLoad(LoadEvent event, LoadType loadType) {
errorIfClosed();
checkTransactionSynchStatus();
LoadEventListener[] loadEventListener = listeners.getLoadEventListeners();
for ( int i = 0; i < loadEventListener.length; i++ ) {
loadEventListener[i].onLoad(event, loadType);
}
}
当然,从这段代码中我们仍然看不出什么头绪,我们继续研究
loadEventListener[i].onLoad(event, loadType);
经查找发现loadEvent有一个listener :DefaultLoadEventListener
其onLoad方法主要调用
event.setResult( load(。。。。 ) ); 也就是 DefaultLoadEventListener 的load方法,而其中主要又调用
Object entity = doLoad(event, persister, keyToLoad, options); 来进行“查询”:
protected Object doLoad(
final LoadEvent event,
final EntityPersister persister,
final EntityKey keyToLoad,
final LoadEventListener.LoadType options)
throws HibernateException {
//1
Object entity = loadFromSessionCache(event, keyToLoad, options);
if ( entity == REMOVED_ENTITY_MARKER ) {
return null;
}
if ( entity != null ) {
return entity;
}
//2
entity = loadFromSecondLevelCache(event, persister, options);
if ( entity != null ) {
return entity;
}
//3
return loadFromDatasource(event, persister, keyToLoad, options);
}
去掉其中的注释和logging部分,我们终于可以看到一个比较明显的语义了!!:::
1、loadFromSessionCache————从session缓存中查找, 如果找不到,则2
2、loadFromSecondLevelCache————从二级缓存中查找(如果支持),如果找不到,则3(即从sessionFactory查询)
3、loadFromDatasource————仍然查找不到,则从数据库中查询——这回是真正的查询
loadFromSessionCache 关键:
Object old = session.getEntityUsingInterceptor( keyToLoad );
loadFromSecondLevelCache关键:
Object ce = persister.getCache().get( ck, source.getTimestamp() );
loadFromDatasource关键:
Object entity = persister.load(
event.getEntityId(),
event.getInstanceToLoad(),
event.getLockMode(),
source
);
先写到这里,有时间再仔细看看。