实体子类的专用缓存区域? [英] Dedicated cache region for entity subclasses?

查看:95
本文介绍了实体子类的专用缓存区域?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们有一个拥有100多个实体类的广泛的实体模型。所有实体类都是单个实体超类的子类。共享缓存模式已设置为 ALL

  @Entity 
@Inheritance( strategy = InheritanceType.JOINED)
@Table(name =entities)
public abstract class LongIdEntity {

@Id
@GeneratedValue(strategy = GenerationType.TABLE )
私人长ID;

@Version
@Column(name =OPT_LOCK_VERSION)
private long lockVersion;

等...

}

一个示例子类:

  @Entity 
@Table(name =cars)
public class Car我们想要缓存第二级缓存中的所有实体。我们希望将所有实体缓存在第二级缓存中。问题是仅为所有实体创建了1个缓存区域;命名为 LongIdEntity



调试显示Hibernate did 查找所有实体类,但仍然为它们指定相同的区域。因为在 SessionFactoryImpl:339

 字符串cacheRegionName = cacheRegionPrefix + model.getRootClass()。getCacheRegionName ); 

在我们的例子中, model.getRootClass()我认为这确实会缓存所有的实体,但没有任何驱逐的控制权。 LongIdEntity 有些类非常频繁且只读。所以我们想让他们固定在记忆中。有些通常在特定时间段内使用,等等......将它们全部放入相同的缓存中使其无效。



在注释中指定区域不起作用。例如:

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

奇怪的是,只有共享缓存模式 ALL 会选取实体类。在任何其他模式下,即使使用@Cache和/或@Cacheable注释,也不会有实体。也许这是一个迹象?



有人有一个想法,我可以如何分配特定实体类特定区域?



TIA: - )


$ b persistence.xml 是基本的:

 <?xml version =1.0encoding =UTF-8?> 
< persistence version =2.0xmlns =http://java.sun.com/xml/ns/persistencexmlns:xsi =http://www.w3.org/2001/XMLSchema-实例
xsi:schemaLocation =http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd\">
< persistence-unit name =carstransaction-type =RESOURCE_LOCAL>
< shared-cache-mode> ALL< / shared-cache-mode>
< / persistence-unit>
< /余辉>

会议工厂是经典的方式:

 < bean id =entityManagerFactoryclass =org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean> 
< property name =persistenceProviderClassvalue =org.hibernate.ejb.HibernatePersistence/>
< property name =persistenceUnitNamevalue =optimus/>
< property name =dataSourceref =dataSource/>
< property name =jpaProperties>
<道具>
< 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>
< /道具>
< / property>
< / bean>

环境


  • JDK6

  • Linux x64

  • Hibernate 4.1.10

  • Spring 3.2.1
  • >


更新:使用@MappedSuperclass

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

不会改变任何东西。

解决方案

Hibernate将整个实体层次结构显式地缓存在一个区域中。这是无法控制的。它是正确处理多态查找的高速缓存分辨率的唯一方法。其他提供者(我认为)确实允许对每个子类的缓存位置/方式进行一些控制(至少这是我根据JPA提供的选项进行的猜测)。


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.

解决方案

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).

这篇关于实体子类的专用缓存区域?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆