Cache de entidades JPA / Providers

Quanto se trabalha com entidades JPA, sabemos que o tempo de sincronização dos dados contidos no EntityManager com os dados armazenados no banco, é pré-definido, então em muitos casos quando uma consulta não traz o resultado esperado no instante em que a query foi executada, pode ser que exista cache agindo sobre essa consulta.

Outros exemplos:

- Quando você faz uma inserção diretamente no banco ( sem a execução de um merge ou persist através do E.M. ).

- Quando existe a execução de uma stored procedure ou package, que faz inserção de dados em banco ( mesmo se esta for chamada como Native Query no E.M. já que o executor será o próprio banco de dados ).


Para solucionar esse problema, utilizamos Hints, esses são propriedades setadas na própria query antes da mesma ser executada no EntityManager, esses hints podem variar de acordo com o provider utilizado.

Esses são detalhes muito importantes que no caso do aprendizado prático, acaba-se deixando de lado, mas é bom sabermos que CACHE faz parte de JPA e precisa ser tratado com determinada importância. Traz grandes benefícios de performance e robustêz à sua aplicação.

Podemos citar os principais providers e seus respectivos hints:

IBM WEBSPHERE:
com.ibm.websphere.jpa.default.provider

ORACLE TOPLINK:
oracle.toplink.essentials.PersistenceProvider

HIBERNATE:
org.hibernate.ejb.HibernatePersistence

Como esse é um vasto assunto e estamos falando de cache, vamos citar os principais Hints para refresh:

************************************
--- Toplink

** Por anotação

Example: JPA Query API

import oracle.toplink.essentials.config.HintValues;
import oracle.toplink.essentials.config.TopLinkQueryHints;
query.setHint(TopLinkQueryHints.REFRESH, HintValues.TRUE);

Example: @QueryHint

import oracle.toplink.essentials.config.HintValues;
import oracle.toplink.essentials.config.TopLinkQueryHints;
@QueryHint(name=TopLinkQueryHints.REFRESH, value=HintValues.TRUE);




** no orm.xml
<entity-mapping<
...
<named-query name="findEmployeesWithName">

<query>SELECT e FROM Employee e WHERE e.name LIKE :empName</query>
<hint name="toplink.refresh" value="true" />
<hint name="toplink.refresh.cascade" value="CascadeAllParts" />
</named-query>
...
<entity-mapping>


** no código
//query ... my query..
query.setHint("toplink.refresh", true);
query.setHint("toplink.refresh.cascade", "CascadeAllParts");




Obs: veja que nesse caso do toplink tanbém existe a propriedade cascade, que faz um refresh tanbém de outros objetos relacionadas com sua Entity.

Leitura:
Mais hints oracle toplink





************************************
---- Eclipselink

*** Anotação
@NamedQuery(name="findEmployeeNoCache",
query="SELECT e FROM Employee e WHERE e.id = :empId",
hints={@QueryHint(name="eclipselink.cache-usage",
value="DoNotCheckCache")})


*** orm.xml
<entity-mapping>
...
<named-query name="findEmployeesWithName">

<query<SELECT e FROM Employee e WHERE e.name LIKE :empName</query>
<hint name="eclipselink.cache-usage" value="DoNotCheckCache"/>
</named-query>
...
<entity-mapping>


Leitura
Documento completo direto do site da IBM

Tudo o que você precisa saber sobre Query Hints






************************************
---Hibernate

***** No código:
query.setHint("org.hibernate.cacheMode", CacheMode.REFRESH)

ex: q.setHint("org.hibernate.cacheable", true);

Assinatura: org.hibernate.cacheable - true/false

Assinatura: org.hibernate.cacheMode - NORMAL / IGNORE / GET / PUT / REFRESH

Assinatura: org.hibernate.cacheRegion - String


Leitura:
Uma discussão muito boa sobre o assunto, site spring framework





2 comentários:

Lellis disse...

Muito obrigado pelas informações. resolveu um pepino grande que eu estava tendo aqui.
Essa cache ainda mata 1 do coração.
abraços.

Anônimo disse...

Estava com dúvida nesse assunto.

Obrigado pelos esclarecimentos! =)