Hi,
We are using hibernate 3.0.5 in our production enviornment. We have set the transaction timeout in the application to be 5 minutes. In the production logs we see many transaction timeout errors while fetching the master data which is cached in second-level cache.
We used Jprofiler to findout the hotspots where the application is spending lot of time. We found that most of the time spent was on fetching the master data. I will explain with an example:
Code:
class OrderLine {
public ProductType getProductTypeOrdered() {
ProductType p = ServiceLocator.getProductService().findProductTypeByCode("code");
return p;
}
}
ProductType is cached in second level cache. The query to find the product type by code is named query in mapping file with cacheable="true" and the cache strategy used on the ProductType object is "nonstrict-read-write". This method getProductTypeOrdered() is called thousands of times for some business validations in a single flow of the request. So we assumed that if the ProductType object is cached, fetching the data from the cache would not take lot of time. Also we did not wanted every OrderLine to hold seperate ProductType object in memory (or is it reference to the original object in second level cache?). We saw that the query to fetch the product type was fired only once. But the amount of time taken to fetch this object is very huge.
We are using EHCache. We changed the above method to intialize the product type object to instance variable of OrderLine object as follows:
Code:
class OrderLine {
private ProductType p = null;
public ProductType getProductTypeOrdered() {
if(p == null) {
p = ServiceLocator.getProductService().findProductTypeByCode("code");
}
return p;
}
ProductType has composite collections which are lazily loaded, we see "collection was evicted" error on certain screens when more than two requests have accessed the product type object. It is not happening when there is only one request is in process. We think this is because there was call to session.clear() somewhere in the middle of the request which evicted the composite collections, so we will have to refresh the object. But we cannot refresh() everytime as it will re-read from the database. This problem occurs on certain screens. But the screen which earlier took more than 60 minutes, now takes about 1 minute to display. This is the reason we are doubting on hibernate's way of fetching the object from cache.
One more thing we observed is that there is call to HibernateTemplate.flushIfNecessary() where jprofiler shows it has taken lot of time.
Are we missing here something? Please let me know if the above information shared is not sufficient. We really need to resolve this asap. Appreciate your help on this.
Thanks,
Ram.