Comment utiliser @Cacheable de JPA2 au lieu de @Cache D'Hibernate

Généralement, j'utilise le @Cache D'Hibernate(utilisation = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE) {[6] } pour mettre en cache une classe @ Entity, et cela fonctionne bien.

En JPA2, il y a une autre annotation @ Cacheable qui semble être la même fonctionnalité avec le @Cache D'Hibernate. Pour rendre ma classe d'entité indépendante du paquet d'hibernate , je veux essayer. Mais je ne peux pas le faire fonctionner. Chaque fois qu'une simple requête d'id frappe toujours la base de données.

Quelqu'un peut-il me dire où va mal ? Grâce.

Classe d'Entité :

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

Classe D'essai:

@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));
  }
}

Le résultat du test montre chaque couche" get " hits DB (avec hibernate.show_sql=true).

Persistance.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"/>

Code JPA:

@Override
public T get(Serializable id)
{
  return em.find(clazz, id);
}
45
demandé sur Pascal Thivent 2010-09-08 05:20:43

2 réponses

Selon la spécification JPA 2.0, Si vous voulez mettre en cache sélectivement des entités à l'aide de l'annotation @Cacheable, Vous êtes censé spécifier un <shared-cache-mode> dans le persistence.xml (ou l'équivalent javax.persistence.sharedCache.mode lors de la création du EntityManagerFactory).

Ci-dessous, un exemple persistence.xml avec l'élément et les propriétés pertinents:

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

Notez que j'ai vu au moins un problème HHH-5303 lié à la mise en cache. Donc, ce qui précède n'est pas garanti:)

Références

  • Hibernate EntityManager guide de référence
  • spécification JPA 2.0
    • Section 3.7.1 "L'élément shared-cache-mode"
    • Section 11.1.7 "Cachable Annotation"
43
répondu Pascal Thivent 2016-10-07 09:19:26

Pour ceux qui utilisent Spring config au lieu de persistence.xml, Voici un exemple:

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

Notez également que si vous utilisez des annotations @Cacheable, vous ne pouvez utiliser qu'une stratégie de concurrence de cache par défaut, qui est déterminée par la méthode getDefaultAccessType() de la RegionFactory. Dans le cas de EhCache, c'est READ_WRITE. Si vous voulez utiliser une autre stratégie, vous devez utiliser les annotations @Cache D'Hibernate.

10
répondu John29 2014-03-27 10:12:37