网上很多言论都说load会使用二级缓存而get不会,包括一些hibernate的教材上也这么写的,但是以前在测试中发现,其实get也会使用二级缓存。
很久以前就发现了这个问题,一直没腾出时间研究,今天特意看了下源码(3.2.6.ga),确实如此
先看一下Session的默认实现SessionImpl
get方法会转到fireLoad,loadType的值是LoadEventListener.GET
load方法也是转到fireLoad,不同的是loadType的值是LoadEventListener.LOAD
- 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);
- }
- }
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的onLoad方法
LoadEventListener的默认实现DefaultLoadEventListener中
最终会转到doLoad方法,options就是前面的loadType
- protected Object doLoad(
- final LoadEvent event,
- final EntityPersister persister,
- final EntityKey keyToLoad,
- final LoadEventListener.LoadType options) throws HibernateException {
- 。。。。。。
- Object entity = loadFromSessionCache( event, keyToLoad, options );//从一级缓存加载
- //如果不为空,直接返回
- 。。。。。。
- entity = loadFromSecondLevelCache(event, persister, options);//从二级缓存加载
- 。。。。。。
- }
protected Object doLoad(
final LoadEvent event,
final EntityPersister persister,
final EntityKey keyToLoad,
final LoadEventListener.LoadType options) throws HibernateException {
。。。。。。
Object entity = loadFromSessionCache( event, keyToLoad, options );//从一级缓存加载
//如果不为空,直接返回
。。。。。。
entity = loadFromSecondLevelCache(event, persister, options);//从二级缓存加载
。。。。。。
}
loadFromSecondLevelCache即是从二级缓存中查找对象
get和load的区别在于LoadEventListener.LoadType options参数,一个是LoadEventListener.GET,一个是LoadEventListener.LOAD
而在这个方法中,并没有用到options参数
也就是说get和load使用二级缓存的状况是一样的,get也会使用二级缓存