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的代理对象在获取对象属性时究竟如何加载数据?在以后的分析中再做详细分析)