Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dedicated cache region for entity subclasses?

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.

@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:

@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 :

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:

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

The weird thing is that only shared cache mode ALL picks up the entity classes. In any other mode no entities are - even when annotated with @Cache and/or @Cacheable. Maybe this is an indication ?

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

TIA :-)

persistence.xml is elementary:

<?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:

  <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

UPDATE: Use @MappedSuperclass

@MappedSuperclass
@Inheritance(strategy = InheritanceType.JOINED)
public abstract class LongIdEntity { ... }

Does not change a thing either.

like image 877
Jan Goyvaerts Avatar asked Mar 08 '13 12:03

Jan Goyvaerts


People also ask

What is Cache region?

Caching Regions are specific region into the cache provider that might store entities, collection or queries. Each cache region resides in a specific cache namespace and has its own lifetime configuration.

What is Cache region in hibernate?

For each entity class, Hibernate will use a separate cache region to store state of instances for that class. The region name is the fully qualified class name. For example, Foo instances are stored in a cache named com.


1 Answers

Hibernate caches the entire entity hierarchy in one region explicitly. There is no control over this. Its the only way to properly handled cached resolution of polymorphic lookups. Other providers (I think) do allow some control over where/how each subclass is cached (at least thats my guess based on the options provided by JPA).

like image 158
Steve Ebersole Avatar answered Oct 23 '22 14:10

Steve Ebersole