I try to understand the caching (second level cache) - I already read the chapter in "hibernate in action". I also tried to find the answer here, but maybe I didnt manage to form the correct search query.
Finally one question is still unclear to me.
We do have a web-application (still with our own persistence). Almost every table do have a compound-key with a first column named "companyNumber".
After the user-login the companyNumber is fixed and cant be changed for the whole session. In Hibernate3 I would use the new session-filter to ensure this.
The problem I have is the cache, if two users uses the same application but are logged in into different companies, and one them updates a table the cache is invalidated - so far so good, but this involved the cache of the other user too, even if he is logged into a different company and the update on the database of the one user do not have to do anything with the other user.
In "hibernate in action" on page 182 you wrote "The second-level cache actually has the scope of a SesssionFactory".
So I thought it would be sufficient to create a SessionFactory per companyNumber, but this isnt true, also setting the "region_prefix" in the configuration (different per companyNumber) doesnt result in the expected behaviour.
Below you might find a short example what I tried to do the "r1" and "r2" parameters are the "region_prefix"es.
This is only an example (tables without the companyNumber) but the expected result should be the same.
Commented inline.
Any idea what I do wrong or what I misunderstood is very welcome.
IMHO the problem is with the UpdateTimestampCache and the StandardQueryCache. There the region_prefix is not taken into account.
Code:
cache.EhCache - Could not find configuration for r1.org.stringfellow.watering.db.WeatherForecastHdr.weatherForecastDtls. Configuring using the defaultCache settings.
cache.EhCache - Could not find configuration for r1.org.stringfellow.watering.db.WeatherForecastHdr. Configuring using the defaultCache settings.
cache.EhCache - Could not find configuration for r1.org.stringfellow.watering.db.WeatherForecastDtl. Configuring using the defaultCache settings.
cache.EhCache - Could not find configuration for net.sf.hibernate.cache.UpdateTimestampsCache. Configuring using the defaultCache settings.
cache.EhCache - Could not find configuration for net.sf.hibernate.cache.StandardQueryCache. Configuring using the defaultCache settings.
cache.EhCache - Could not find configuration for r2.org.stringfellow.watering.db.WeatherForecastHdr.weatherForecastDtls. Configuring using the defaultCache settings.
cache.EhCache - Could not find configuration for r2.org.stringfellow.watering.db.WeatherForecastHdr. Configuring using the defaultCache settings.
cache.EhCache - Could not find configuration for r2.org.stringfellow.watering.db.WeatherForecastDtl. Configuring using the defaultCache settings.
After implementing my own CacheProvider:
Code:
public Cache buildCache(String name, Properties properties) throws CacheException
{
String company = properties.getProperty("hibernate.cache.region_prefix", "glob");
return super.buildCache(company +"."+name, properties);
}
It worked, but might this have some side-effects in hibernate if I change the naming - and thus create UpdateTimestampsCahe and StandardQueryCache twice?
Hibernate version: Hibernate 2.1
Mapping documents: <cache usage="read-write"/>
added to my mappings
Code between sessionFactory.openSession() and session.close():Code:
SessionFactory factory1 = Storage.createFactory("r1");
Session session1 = factory1.openSession();
Transaction tx1 = session1.beginTransaction();
SessionFactory factory2 = Storage.createFactory("r2");
Session session2 = factory2.openSession();
Transaction tx2 = session2.beginTransaction();
[i]// popuplate the cache in region 1 - session1[/i]
Query crit1 = session1.createQuery("from WeatherForecastHdr f where f.comp_id.companyNumber = 1");
crit1.setCacheable(true);
List allHdr = crit1.list();
System.err.println("1: " + allHdr.size());
[i]// popuplate the cache in region 2 - session2[/i]
Query crit2 = session2.createQuery("from WeatherForecastHdr f where f.comp_id.companyNumber = 2");
crit2.setCacheable(true);
allHdr = crit2.list();
System.err.println("2: " + allHdr.size());
[i]// read&update data via session 1[/i]
WeatherForecastHdr data = (WeatherForecastHdr) session1.load(WeatherForecastHdr.class, new WeatherForecastHdrPK(1, "xx", "yy"));
System.err.println("pre update:" + data.getRegion());
data.setRegion(new Date().toString());
System.err.println("post update:" + data.getRegion());
tx1.commit();
[i]// repopulate data in region 1 - session 1[/i]
crit1 = session1.createQuery("from WeatherForecastHdr f where f.comp_id.companyNumber = 1");
crit1.setCacheable(true);
allHdr = crit1.list();
System.err.println("1: " + allHdr.size());
[i]// access cached data in region 2 - session 2 - this should not repopulate the cache[/i]
crit2 = session2.createQuery("from WeatherForecastHdr f where f.comp_id.companyNumber = 2");
crit2.setCacheable(true);
allHdr = crit2.list();
System.err.println("2: " + allHdr.size());
tx1.commit();
session1.close();
[i]// get data in region 2 - session 2[/i]
data = (WeatherForecastHdr) session2.load(WeatherForecastHdr.class, new WeatherForecastHdrPK(2, "xx", "yy"));
System.err.println("other company:" + data.getRegion());
tx2.commit();
session2.close();
Name and version of the database you are using:postgresql 8.0 beta-1
The generated SQL (show_sql=true):Code:
Sun Oct 24 11:24:29 CEST 2004 WARN [main] cache.EhCache - Could not find configuration for r1.org.stringfellow.watering.db.WeatherForecastHdr.weatherForecastDtls. Configuring using the defaultCache settings.
Sun Oct 24 11:24:29 CEST 2004 WARN [main] cache.EhCache - Could not find configuration for r1.org.stringfellow.watering.db.WeatherForecastHdr. Configuring using the defaultCache settings.
Sun Oct 24 11:24:29 CEST 2004 WARN [main] cache.EhCache - Could not find configuration for r1.org.stringfellow.watering.db.WeatherForecastDtl. Configuring using the defaultCache settings.
Sun Oct 24 11:24:29 CEST 2004 WARN [main] cache.EhCache - Could not find configuration for net.sf.hibernate.cache.UpdateTimestampsCache. Configuring using the defaultCache settings.
Sun Oct 24 11:24:29 CEST 2004 WARN [main] cache.EhCache - Could not find configuration for net.sf.hibernate.cache.StandardQueryCache. Configuring using the defaultCache settings.
Sun Oct 24 11:24:29 CEST 2004 WARN [main] cache.EhCache - Could not find configuration for r2.org.stringfellow.watering.db.WeatherForecastHdr.weatherForecastDtls. Configuring using the defaultCache settings.
Sun Oct 24 11:24:29 CEST 2004 WARN [main] cache.EhCache - Could not find configuration for r2.org.stringfellow.watering.db.WeatherForecastHdr. Configuring using the defaultCache settings.
Sun Oct 24 11:24:29 CEST 2004 WARN [main] cache.EhCache - Could not find configuration for r2.org.stringfellow.watering.db.WeatherForecastDtl. Configuring using the defaultCache settings.
[i]// read&update data via session 1[/i]
Hibernate: select weatherfor0_.w00_company_number as w00_comp1_, weatherfor0_.w00_originclass as w00_orig2_, weatherfor0_.w00_acid as w00_acid, weatherfor0_.w00_version as w00_vers4_, weatherfor0_.w00_lastget as w00_last5_, weatherfor0_.w00_city as w00_city, weatherfor0_.w00_country as w00_coun7_, weatherfor0_.w00_region as w00_region from w00_weather_forecast_hdr weatherfor0_ where (weatherfor0_.w00_company_number=1 )
Hibernate: select weatherfor0_.w01_company_number as w01_comp1___, weatherfor0_.w01_originclass as w01_orig2___, weatherfor0_.w01_acid as w01_acid__, weatherfor0_.w01_date as w01_date__, weatherfor0_.w01_company_number as w01_comp1_0_, weatherfor0_.w01_originclass as w01_orig2_0_, weatherfor0_.w01_acid as w01_acid0_, weatherfor0_.w01_date as w01_date0_, weatherfor0_.w01_version as w01_vers5_0_, weatherfor0_.w01_current as w01_curr6_0_, weatherfor0_.w01_temp as w01_temp0_, weatherfor0_.w01_temphi as w01_temphi0_, weatherfor0_.w01_templo as w01_templo0_, weatherfor0_.w01_rains as w01_rains0_, weatherfor0_.w01_condition as w01_con11_0_, weatherfor0_.w01_conditiontext as w01_con12_0_, weatherfor0_.w01_conditionimage as w01_con13_0_, weatherfor0_.w01_company_number as w01_comp1_0_, weatherfor0_.w01_originclass as w01_orig2_0_, weatherfor0_.w01_acid as w01_acid0_ from w01_weather_forecast_dtl weatherfor0_ where weatherfor0_.w01_company_number=? and weatherfor0_.w01_originclass=? and weatherfor0_.w01_acid=?
1: 1
[i]// popuplate the cache in region 2 - session2[/i]
Hibernate: select weatherfor0_.w00_company_number as w00_comp1_, weatherfor0_.w00_originclass as w00_orig2_, weatherfor0_.w00_acid as w00_acid, weatherfor0_.w00_version as w00_vers4_, weatherfor0_.w00_lastget as w00_last5_, weatherfor0_.w00_city as w00_city, weatherfor0_.w00_country as w00_coun7_, weatherfor0_.w00_region as w00_region from w00_weather_forecast_hdr weatherfor0_ where (weatherfor0_.w00_company_number=2 )
Hibernate: select weatherfor0_.w01_company_number as w01_comp1___, weatherfor0_.w01_originclass as w01_orig2___, weatherfor0_.w01_acid as w01_acid__, weatherfor0_.w01_date as w01_date__, weatherfor0_.w01_company_number as w01_comp1_0_, weatherfor0_.w01_originclass as w01_orig2_0_, weatherfor0_.w01_acid as w01_acid0_, weatherfor0_.w01_date as w01_date0_, weatherfor0_.w01_version as w01_vers5_0_, weatherfor0_.w01_current as w01_curr6_0_, weatherfor0_.w01_temp as w01_temp0_, weatherfor0_.w01_temphi as w01_temphi0_, weatherfor0_.w01_templo as w01_templo0_, weatherfor0_.w01_rains as w01_rains0_, weatherfor0_.w01_condition as w01_con11_0_, weatherfor0_.w01_conditiontext as w01_con12_0_, weatherfor0_.w01_conditionimage as w01_con13_0_, weatherfor0_.w01_company_number as w01_comp1_0_, weatherfor0_.w01_originclass as w01_orig2_0_, weatherfor0_.w01_acid as w01_acid0_ from w01_weather_forecast_dtl weatherfor0_ where weatherfor0_.w01_company_number=? and weatherfor0_.w01_originclass=? and weatherfor0_.w01_acid=?
2: 1
[i]// read&update data via session 1[/i]
pre update:Sun Oct 24 11:24:15 CEST 2004
post update:Sun Oct 24 11:24:30 CEST 2004
Hibernate: update w00_weather_forecast_hdr set w00_version=?, w00_region=? where w00_company_number=? and w00_originclass=? and w00_acid=? and w00_version=?
[i]// repopulate data in region 1 - session 1[/i]
Hibernate: select weatherfor0_.w00_company_number as w00_comp1_, weatherfor0_.w00_originclass as w00_orig2_, weatherfor0_.w00_acid as w00_acid, weatherfor0_.w00_version as w00_vers4_, weatherfor0_.w00_lastget as w00_last5_, weatherfor0_.w00_city as w00_city, weatherfor0_.w00_country as w00_coun7_, weatherfor0_.w00_region as w00_region from w00_weather_forecast_hdr weatherfor0_ where (weatherfor0_.w00_company_number=1 )
1: 1
[i]// get data in region 1 - session 1 - this select should not happen[/i]
Hibernate: select weatherfor0_.w00_company_number as w00_comp1_, weatherfor0_.w00_originclass as w00_orig2_, weatherfor0_.w00_acid as w00_acid, weatherfor0_.w00_version as w00_vers4_, weatherfor0_.w00_lastget as w00_last5_, weatherfor0_.w00_city as w00_city, weatherfor0_.w00_country as w00_coun7_, weatherfor0_.w00_region as w00_region from w00_weather_forecast_hdr weatherfor0_ where (weatherfor0_.w00_company_number=2 )
2: 1
other company:null