-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 4 posts ] 
Author Message
 Post subject: strictly parted cache?
PostPosted: Sun Oct 24, 2004 5:28 am 
Regular
Regular

Joined: Thu Dec 11, 2003 4:14 pm
Posts: 86
Location: Hibernate 3 + annotations, Oracle 9i, PostgreSQL 8.0, Java 1.5.0
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


Top
 Profile  
 
 Post subject: Problem found!
PostPosted: Mon Oct 25, 2004 3:45 am 
Regular
Regular

Joined: Thu Dec 11, 2003 4:14 pm
Posts: 86
Location: Hibernate 3 + annotations, Oracle 9i, PostgreSQL 8.0, Java 1.5.0
The problem is in org.hibernate.cache.EhCache

Code:
    public EhCache(String name) throws CacheException {
        try {
            CacheManager manager = CacheManager.getInstance();
            cache = manager.getCache(name);


There the CacheManager is used as singleton (CacheManager.getInstance()) and therefore shared among all other SessionFactories.
Thus the table/query/timestamp caches are also shared.

I think I managed to create a patch for this, will test it and send it to JIRA.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Oct 25, 2004 5:40 am 
Regular
Regular

Joined: Thu Dec 11, 2003 4:14 pm
Posts: 86
Location: Hibernate 3 + annotations, Oracle 9i, PostgreSQL 8.0, Java 1.5.0
Uhm, it looks like it is not possible to create multiple CacheManager with ehcache. This is odd.

Now I need some advice from the hibernate team.
Shoud I try to create a patch which adds the session region_prefix to the QueryCache and UpdateTimestampCache?
To accommodate the documentation the right-right way is to prefix the cache-key with an SessionFactory object identifier, but the SessionFactory is not reachable. Maybe we could add a entry to the properties?

Or should I simply use my workaround above (own cache provider). But then I think the ehcache need some documentation being not able to have separated caches per SessionFactory.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Oct 27, 2004 3:13 am 
Regular
Regular

Joined: Thu Dec 11, 2003 4:14 pm
Posts: 86
Location: Hibernate 3 + annotations, Oracle 9i, PostgreSQL 8.0, Java 1.5.0
After filing a bug at JIRA this has been fixed in 2 hours in HB3 - bloody fast.

Many thanks to the hibernate team!

Just for the records:
http://opensource.atlassian.com/project ... se/HB-1280


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 4 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.