【问题标题】:How to use JPA2's @Cacheable instead of Hibernate's @Cache如何使用 JPA2 的 @Cacheable 而不是 Hibernate 的 @Cache
【发布时间】:2011-04-09 12:05:01
【问题描述】:

通常,我使用 Hibernate 的 @Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE) 来缓存 @Entity 类,它运行良好。

在 JPA2 中,还有另一个 @Cacheable 注释,它似乎与 Hibernate 的 @Cache 功能相同。为了让我的实体类独立于hibernate的包,我想试一试。但我不能让它工作。每次一个简单的 id 查询仍然命中 DB。

谁能告诉我哪里出错了?谢谢。

实体类:

@Entity
//@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
@Cacheable(true) 
public class User implements Serializable
{
 // properties
}

测试类:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"classpath:app.xml"})
@TransactionConfiguration(transactionManager="transactionManager")
public class UserCacheTest
{
  @Inject protected UserDao userDao;

  @Transactional
  @Test
  public void testGet1()
  {
    assertNotNull(userDao.get(2L));
  }

  @Transactional
  @Test
  public void testGet2()
  {
    assertNotNull(userDao.get(2L));
  }

  @Transactional
  @Test
  public void testGet3()
  {
    assertNotNull(userDao.get(2L));
  }
}

测试结果显示每个“get”命中数据库层(hibernate.show_sql=true)。

Persistence.xml:

<property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect"/>
<property name="hibernate.show_sql" value="true"/>
<property name="hibernate.format_sql" value="true" />
<property name="hibernate.use_outer_join" value="true"/>

<property name="hibernate.cache.provider_class" value="org.hibernate.cache.SingletonEhCacheProvider"/>
<property name="hibernate.cache.use_second_level_cache" value="true"/>
<property name="hibernate.cache.use_query_cache" value="true"/>

JPA 代码:

@Override
public T get(Serializable id)
{
  return em.find(clazz, id);
}

【问题讨论】:

    标签: hibernate orm jpa caching jpa-2.0


    【解决方案1】:

    根据 JPA 2.0 规范,如果您想使用 @Cacheable 注释有选择地缓存实体,您应该在 persistence.xml 中指定一个 &lt;shared-cache-mode&gt;(或在创建 @ 时等效的 javax.persistence.sharedCache.mode 987654327@).

    下面是一个带有相关元素和属性的示例persistence.xml:

    <persistence 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" version="2.0">
      <persistence-unit name="FooPu" transaction-type="RESOURCE_LOCAL">
        <provider>org.hibernate.ejb.HibernatePersistence</provider>
        ...
        <shared-cache-mode>ENABLE_SELECTIVE</shared-cache-mode>
        <properties>
          ...
          <property name="hibernate.cache.provider_class" value="org.hibernate.cache.SingletonEhCacheProvider"/>
          <property name="hibernate.cache.use_second_level_cache" value="true"/>
          <property name="hibernate.cache.use_query_cache" value="true"/>
        </properties>
      </persistence-unit>
    </persistence>
    

    请注意,我至少看到了一个与缓存相关的问题HHH-5303。所以以上不能保证:)

    参考文献

    • Hibernate EntityManager 参考指南
    • JPA 2.0 规范
      • 第 3.7.1 节“共享缓存模式元素”
      • 第 11.1.7 节“可缓存注释”

    【讨论】:

    • 谢谢,它似乎在 3.5.5-Final 中仍然无法正常工作。无论如何,我会留意 HHH-5303。谢谢。
    • 这些说明使用 3.5.5-Final 和 ehcache 2.3.1 对我有用
    • 它可能不适用于 3.5.5,因为我认为 JPA 2.0 由 hibernate 4.0 它自己支持。
    【解决方案2】:

    对于那些使用 Spring config 而不是 persistence.xml 的人,这里是一个示例:

    <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="dataSource" ref="dataSource"/>
        <property name="jpaVendorAdapter">
            <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
                <property name="database" value="MYSQL"/>
                <property name="databasePlatform" value="org.hibernate.dialect.MySQL5InnoDBDialect"/>
                <property name="showSql" value="true"/>
                <property name="generateDdl" value="false"/>
            </bean>
        </property>
        <property name="packagesToScan" value="com.mycompany.myproject.domain"/>
        <property name="jpaPropertyMap">
            <map>
                <entry key="hibernate.cache.region.factory_class" value="org.hibernate.cache.ehcache.SingletonEhCacheRegionFactory"/>
                <entry key="hibernate.cache.use_second_level_cache" value="true"/>
                <entry key="hibernate.cache.use_query_cache" value="true"/>
                <entry key="javax.persistence.sharedCache.mode" value="ENABLE_SELECTIVE" />
            </map>
        </property>
    </bean>
    

    另外注意,如果你使用@Cacheable注解,你只能使用一个默认的缓存并发策略,这个策略是由RegionFactory的getDefaultAccessType()方法决定的。对于 EhCache,它是 READ_WRITE。如果要使用其他策略,则必须使用 Hibernate 的@Cache 注解。

    【讨论】:

    • 是做什么用的?它会使用hibernate的缓存吗?
    • @Scarlett 它指定 Hibernate 将使用哪个缓存实现来进行二级缓存。它被描述为here。
    • 注意:从 4.0 开始,可以全局配置默认策略,而不依赖于代码中的 hibernate 包,请参阅docs.jboss.org/hibernate/orm/4.0/devguide/en-US/html/ch06.html
    猜你喜欢
    • 2015-06-03
    • 2021-10-12
    • 1970-01-01
    • 1970-01-01
    • 2014-12-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-03
    相关资源
    最近更新 更多