I'm using Hibernate with 2nd level cache using Ehcache. I found that if the result returned from session.get() (searching by primary key) is NULL, the value will not be cached in both 1st level and 2nd level cache and SQL will be fired to database again. There is no problem if the value returned is not null for the same entity.
I have debug using the hibernate and ehcache source and I'm sure that the cache is enabled and called properly. Here are my findings of the problem:
In the EntityLoader(Loader).initializeEntitiesAndCollections method, if there is no result returned from database, the hydratedObjects is empty. So the method TwoPhaseLoad.initializeEntity (which will put the result into the cache) will never be called.
Code:
EntityLoader(Loader).initializeEntitiesAndCollections(...)
...
for ( int i = 0; i < hydratedObjectsSize; i++ ) {
...TwoPhaseLoad.initializeEntity(...)
Code:
TwoPhaseLoad.initializeEntity(...)
...persister.getCache().put(...
Actually the null value is expected to be cached also as the same criteria will always return null, no matter how many times I called to database.
I have browser all hibernate and ehcache documentation and forum and no related config is available. Ehcache ifself support null value for caching. There is also no documentation saying that null value from session.get() cannot be cached. Actually, I have post to JIRA Issue tracking system but is rejected with unknown reason.
http://opensource.atlassian.com/project ... e/HHH-3522In our system, we will redirect the request to other system based the existence of customerId in our system. So, if NULL value cannot be cached, there will be a large number of redundant SQLs fired to database which will greatly affect our performance.
Do anyone have solution for this situation? Thanks all for your help!
Hibernate version: 3.2.5
Mapping documents:N/A
Full stack trace of debug that comes to point of failure:Code:
EntityLoader(Loader).initializeEntitiesAndCollections(List, Object, SessionImplementor, boolean) line: 848
EntityLoader(Loader).doQuery(SessionImplementor, QueryParameters, boolean) line: 729
EntityLoader(Loader).doQueryAndInitializeNonLazyCollections(SessionImplementor, QueryParameters, boolean) line: 236
EntityLoader(Loader).loadEntity(SessionImplementor, Object, Type, Object, String, Serializable, EntityPersister) line: 1860
EntityLoader(AbstractEntityLoader).load(SessionImplementor, Object, Object, Serializable) line: 48
EntityLoader(AbstractEntityLoader).load(Serializable, Object, SessionImplementor) line: 42
SingleTableEntityPersister(AbstractEntityPersister).load(Serializable, Object, LockMode, SessionImplementor) line: 3044
DefaultLoadEventListener.loadFromDatasource(LoadEvent, EntityPersister, EntityKey, LoadEventListener$LoadType) line: 395
DefaultLoadEventListener.doLoad(LoadEvent, EntityPersister, EntityKey, LoadEventListener$LoadType) line: 375
DefaultLoadEventListener.load(LoadEvent, EntityPersister, EntityKey, LoadEventListener$LoadType) line: 139
DefaultLoadEventListener.proxyOrLoad(LoadEvent, EntityPersister, EntityKey, LoadEventListener$LoadType) line: 195
DefaultLoadEventListener.onLoad(LoadEvent, LoadEventListener$LoadType) line: 103
SessionImpl.fireLoad(LoadEvent, LoadEventListener$LoadType) line: 878
SessionImpl.get(String, Serializable) line: 815
SessionImpl.get(Class, Serializable) line: 808
Name and version of the database you are using:Oracle10g[/code]