-->
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.  [ 11 posts ] 
Author Message
 Post subject: 2nd level caching problem: one cache for all.
PostPosted: Mon Mar 11, 2013 6:31 am 
Newbie

Joined: Mon Dec 15, 2008 7:10 am
Posts: 12
We have an extensive entity model with 100+ entity classes. All the entity classes are subclasses of a single entity superclasses. The shared cache mode has been set to ALL.

Code:
    @Entity
    @Inheritance(strategy = InheritanceType.JOINED)
    @Table(name = "entities")
    public abstract class LongIdEntity {
   
      @Id
      @GeneratedValue(strategy = GenerationType.TABLE)
      private Long id;
   
      @Version
      @Column(name = "OPT_LOCK_VERSION")
      private Long lockVersion;
   
      etc...
   
    }


An example subclass:

Code:
    @Entity
    @Table(name = "cars")
    public class Car extends LongIdEntity { ... }


We'd like to cache all entities in the 2nd level cache. The problem is that only 1 cache region is made for all the entities; named LongIdEntity.

Debugging shows Hibernate *did* find all the entity classes, but assigns them the same region anyway. Because at SessionFactoryImpl:339 :

Code:
    String cacheRegionName = cacheRegionPrefix + model.getRootClass().getCacheRegionName();


In our case, the call to model.getRootClass() will always yield "LongIdEntity".

I presume this would indeed cache all the entities, but without any control of eviction. Some classes are very frequent and read-only. So we want to keep them pinned into memory. Some are typically used in a certain time span, etc... Cramming it all into the same cache invalidates it all.

Specifying the region in the annotation has no effect. For example:

Code:
    @Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE,region = "cars")
    @Entity
    @Table(name = "cars")
    public class Car extends LongIdEntity { ... }


Somebody has an idea how I can assign specific entity classes specific regions ?

TIA :-)

persistence.xml is elementary:

Code:
    <?xml version="1.0" encoding="UTF-8"?>
    <persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                 xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
      <persistence-unit name="cars" transaction-type="RESOURCE_LOCAL">
        <shared-cache-mode>ALL</shared-cache-mode>
      </persistence-unit>
    </persistence>



The session factory is made the classic way:

Code:
      <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="persistenceProviderClass" value="org.hibernate.ejb.HibernatePersistence"/>
        <property name="persistenceUnitName" value="optimus"/>
        <property name="dataSource" ref="dataSource"/>
        <property name="jpaProperties">
          <props>
            <prop key="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.SingletonEhCacheRegionFactory</prop>
            <prop key="hibernate.cache.use_second_level_cache">true</prop>
            <prop key="hibernate.cache.use_query_cache">true</prop>
            <prop key="hibernate.generate_statistics">true</prop>
            <prop key="hibernate.cache.default_cache_concurrency_strategy">NONSTRICT_READ_WRITE</prop>
            <prop key="hibernate.hbm2ddl.auto">update</prop>
            <prop key="hibernate.jdbc.batch_size">1000</prop>
            <prop key="hibernate.show_sql">false</prop>
            <prop key="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</prop>
            <prop key="hibernate.search.default.directory_provider">filesystem</prop>
            <prop key="hibernate.search.default.indexBase">/hibernate-search</prop>
          </props>
        </property>
      </bean>


The environment

- JDK6
- Linux x64
- Hibernate 4.1.10
- Spring 3.2.1


Top
 Profile  
 
 Post subject: Re: 2nd level caching problem: one cache for all.
PostPosted: Mon Mar 11, 2013 10:34 am 
Expert
Expert

Joined: Tue Jun 16, 2009 3:36 am
Posts: 990
Solution: annotate LongIdEntity class with @MappedSuperclass instead of annotating it as @Entity
In this way your normal entity classes are no more handled all together as persistent subclasses and so you can sucessfully define separate cache regions.


Top
 Profile  
 
 Post subject: Re: 2nd level caching problem: one cache for all.
PostPosted: Mon Mar 11, 2013 11:09 am 
Newbie

Joined: Mon Dec 15, 2008 7:10 am
Posts: 12
Nope - it doesn't. :-)

I've tried it before - but double checked again just in case. And to make sure I'm checking EHCache with JMX to see what caches were created. As does the logging.

Making the superclass a mapped superclass as shown here:
Code:
@MappedSuperclass
@Inheritance(strategy = InheritanceType.JOINED)
public abstract class LongIdEntity { ... }

... does not change a thing. Because the call to getRootClass() still yields LongIdEntity. :-/

--

Setting the shared cache mode to ALL does, without any entity annotated with @Cache results in *no* entity cached at all. I've only get the regular query cache and its companion update time stamp cache. (Isn't ALL supposed to find and cache all the entity classes ?)

Setting the share case mode to ENABLE_SELECTIVE w/o annotating the super class also results in no caching. It's only when both the super class and subclass are annotated that a cache is created. Named LongIdEntity.

@Cacheable seems to behave exactly as @Cache. Both the classes have to be annotated.


Top
 Profile  
 
 Post subject: Re: 2nd level caching problem: one cache for all.
PostPosted: Tue Mar 12, 2013 3:04 am 
Expert
Expert

Joined: Tue Jun 16, 2009 3:36 am
Posts: 990
I don't want to get into long discussions, anyway I use
Hibernate4.1.10 , EHCache as 2L-Cache, following Mapped Superclass:

Code:
@MappedSuperclass
public abstract class AbstractBasePersistentObject{
   @GenericGenerator(name = "idGenerator", strategy = "org.hibernate.id.enhanced.TableGenerator", parameters = { @Parameter(name = "increment_size", value = "100"), @Parameter(name = "optimizer", value = "pooled-lo"),@Parameter(name = "prefer_entity_table_as_segment_value", value = "true") })
   @Id @GeneratedValue(generator = "idGenerator")
    @Column(name = "OID")
    private long oid;
 
   ...


and all my other entity classes are implemented like this:

Code:
@Entity
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE, region="Eternal")
@NaturalIdCache (region="org.hibernate.cache.LookupNaturalId")
public class GCurrencyPeer extends AbstractBasePersistentObject
{
    @Column(columnDefinition = "nvarchar(255)")
    @NaturalId (mutable = true)
    private String code;
...
}

@Entity
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE, region="TenMinutes")
@NaturalIdCache (region="org.hibernate.cache.LookupNaturalId")
public class Country extends AbstractBasePersistentObject
{
    @Column(columnDefinition = "nvarchar(255)")
    @NaturalId (mutable = true)
    private String code;
...
}



And the caching into different cache regions works great.
N.B.: I use exclusively table per class hierarchy inheritance strategy.


Top
 Profile  
 
 Post subject: Re: 2nd level caching problem: one cache for all.
PostPosted: Tue Mar 12, 2013 4:08 am 
Newbie

Joined: Mon Dec 15, 2008 7:10 am
Posts: 12
Is the JPA inheritance strategy of importance for caching ?

I'm using joined because of polymorphism in relationships. Hibernate was complaining I was trying something that is only allowed with joined. :-)

I never had any problem with cache regions before - but neither was I using that inheritance strategy either...


Top
 Profile  
 
 Post subject: Re: 2nd level caching problem: one cache for all.
PostPosted: Fri Mar 15, 2013 9:44 am 
Newbie

Joined: Mon Dec 15, 2008 7:10 am
Posts: 12
bump...


Top
 Profile  
 
 Post subject: Re: 2nd level caching problem: one cache for all.
PostPosted: Mon Mar 18, 2013 3:24 am 
Expert
Expert

Joined: Tue Jun 16, 2009 3:36 am
Posts: 990
Sorry I have no experience with joined inheritance strategy at all.
Maybe someone other here in the forum can helt artisan?


Top
 Profile  
 
 Post subject: Re: 2nd level caching problem: one cache for all.
PostPosted: Mon Mar 18, 2013 6:15 am 
Newbie

Joined: Mon Dec 15, 2008 7:10 am
Posts: 12
Logically it's just another way of mapping entities into the database.

For all what I know, it's of no concern to the object model. But then again, it's the first time I'm using this inheritance strategy too.


Top
 Profile  
 
 Post subject: Re: 2nd level caching problem: one cache for all.
PostPosted: Tue Mar 19, 2013 5:48 am 
Newbie

Joined: Mon Dec 15, 2008 7:10 am
Posts: 12
Can you tell me what cache provider class you use ? Maybe that's the problem.

I came to me this morning that SingletonEhCacheRegionFactory might mean it IS supposed to manage a single big region. :-)


Top
 Profile  
 
 Post subject: Re: 2nd level caching problem: one cache for all.
PostPosted: Wed Mar 20, 2013 3:32 am 
Expert
Expert

Joined: Tue Jun 16, 2009 3:36 am
Posts: 990
<property name="hibernate.cache.region.factory_class" value="org.hibernate.cache.ehcache.SingletonEhCacheRegionFactory"/>

Ehcache Core version = 2.5.1
Hibernate version = 4.1.10


Top
 Profile  
 
 Post subject: Re: 2nd level caching problem: one cache for all.
PostPosted: Wed Mar 20, 2013 5:33 am 
Newbie

Joined: Mon Dec 15, 2008 7:10 am
Posts: 12
So that's not that either... :-)

But according to a discussion I started on SO this is not possible anyway ! :-p
http://stackoverflow.com/questions/15294394/dedicated-cache-region-for-entity-subclasses

I am DEAD sure it used to work on Hibernate 3. And you can make it work on Hibernate 4.

But I've got no time to chase this any further now.


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 11 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.