Ok, just implemented second approach (build on top of first one) - tested it with Hibernate 4.x.
You'll just have to set query hint "javax.persistence.cache.retrieveMode" to USE : public List<Civilite> findAllCivilite() { return entityManager .createNamedQuery(NamedQueries.CIVILITE_FIND_ALL, Civilite.class) .setHint("javax.persistence.cache.retrieveMode", CacheRetrieveMode.USE) .getResultList(); } And use an em produced / decorated like that : public class EntityManagerConfigProducer { @PersistenceContext private EntityManager entityManager; @Produces public EntityManager getEntityManager() { return new PortableEntityManager(entityManager); } } Regards, Adrian P.S. Here's the code I've used for this : === PortableEntityManager.java (don't like the name :( ) public class PortableEntityManager extends DelegatingEntityManager { private static final String RETRIEVE_MODE = "javax.persistence.cache.retrieveMode"; private static final String STORE_MODE = "javax.persistence.cache.storeMode"; public PortableEntityManager(EntityManager em) { super(em); } @Override public Query createQuery(String qlString) { return new CacheSupportQuery(getDelegate().createQuery(qlString)); } @Override public <T> TypedQuery<T> createQuery(CriteriaQuery<T> criteriaQuery) { return new CacheSupportTypedQuery<T>(getDelegate().createQuery(criteriaQuery)); } @Override public <T> TypedQuery<T> createQuery(String qlString, Class<T> resultClass) { return new CacheSupportTypedQuery<T>(getDelegate().createQuery(qlString, resultClass)); } @Override public Query createNamedQuery(String name) { return new CacheSupportQuery(getDelegate().createNamedQuery(name)); } @Override public <T> TypedQuery<T> createNamedQuery(String name, Class<T> resultClass) { return new CacheSupportTypedQuery<T>(getDelegate().createNamedQuery(name, resultClass)); } @Override public Query createNativeQuery(String sqlString) { return new CacheSupportQuery(getDelegate().createNativeQuery(sqlString)); } @Override public Query createNativeQuery(String sqlString, @SuppressWarnings("rawtypes") Class resultClass) { return new CacheSupportQuery(getDelegate().createNativeQuery(sqlString, resultClass)); } @Override public Query createNativeQuery(String sqlString, String resultSetMapping) { return new CacheSupportQuery(getDelegate().createNativeQuery(sqlString, resultSetMapping)); } public static class CacheSupportTypedQuery<X> extends DelegatingTypedQuery<X> { public CacheSupportTypedQuery(TypedQuery<X> query) { super(query); } @Override public TypedQuery<X> setHint(String hintName, Object value) { return portableQueryHint(hintName, value, this); } } public static class CacheSupportQuery extends DelegatingQuery { public CacheSupportQuery(Query query) { super(query); } @Override public Query setHint(String hintName, Object value) { return portableQueryHint(hintName, value, this); } } private static <Q extends DelegatingQuery> Q portableQueryHint(String hintName, Object value, Q query) { Object retrievalMode = null; Object storeMode = null; boolean cacheHint = false; if (RETRIEVE_MODE.equals(hintName)) { retrievalMode = value; storeMode = (query.getHints() != null ? query.getHints().get(STORE_MODE) : null); cacheHint = true; } else if (STORE_MODE.equals(hintName)) { retrievalMode = (query.getHints() != null ? query.getHints().get(RETRIEVE_MODE) : null); storeMode = value; cacheHint = true; } if (cacheHint) { if ((storeMode != null && !storeMode .equals(CacheStoreMode.BYPASS)) || (retrievalMode != null && !retrievalMode .equals(CacheStoreMode.BYPASS))) { JpaUtils.cacheQuery(query.getDelegate(), true); } else { JpaUtils.cacheQuery(query.getDelegate(), false); } } query.getDelegate().setHint(hintName, value); return query; } } === DelegatingEntityManager.java public class DelegatingEntityManager implements EntityManager { private EntityManager em; public DelegatingEntityManager(EntityManager em) { this.em = em; } @Override public void persist(Object entity) { em.persist(entity); } @Override public <T> T merge(T entity) { return em.merge(entity); } @Override public void remove(Object entity) { em.remove(entity); } @Override public <T> T find(Class<T> entityClass, Object primaryKey) { return em.find(entityClass, primaryKey); } @Override public <T> T find(Class<T> entityClass, Object primaryKey, Map<String, Object> properties) { return em.find(entityClass, primaryKey, properties); } @Override public <T> T find(Class<T> entityClass, Object primaryKey, LockModeType lockMode) { return em.find(entityClass, primaryKey, lockMode); } @Override public <T> T find(Class<T> entityClass, Object primaryKey, LockModeType lockMode, Map<String, Object> properties) { return em.find(entityClass, primaryKey, lockMode, properties); } @Override public <T> T getReference(Class<T> entityClass, Object primaryKey) { return em.getReference(entityClass, primaryKey); } @Override public void flush() { em.flush(); } @Override public void setFlushMode(FlushModeType flushMode) { em.setFlushMode(flushMode); } @Override public FlushModeType getFlushMode() { return em.getFlushMode(); } @Override public void lock(Object entity, LockModeType lockMode) { em.lock(entity, lockMode); } @Override public void lock(Object entity, LockModeType lockMode, Map<String, Object> properties) { em.lock(entity, lockMode, properties); } @Override public void refresh(Object entity) { em.refresh(entity); } @Override public void refresh(Object entity, Map<String, Object> properties) { em.refresh(entity, properties); } @Override public void refresh(Object entity, LockModeType lockMode) { em.refresh(entity, lockMode); } @Override public void refresh(Object entity, LockModeType lockMode, Map<String, Object> properties) { em.refresh(entity, lockMode, properties); } @Override public void clear() { em.clear(); } @Override public void detach(Object entity) { em.detach(entity); } @Override public boolean contains(Object entity) { return em.contains(entity); } @Override public LockModeType getLockMode(Object entity) { return em.getLockMode(entity); } @Override public void setProperty(String propertyName, Object value) { em.setProperty(propertyName, value); } @Override public Map<String, Object> getProperties() { return em.getProperties(); } @Override public Query createQuery(String qlString) { return em.createQuery(qlString); } @Override public <T> TypedQuery<T> createQuery(CriteriaQuery<T> criteriaQuery) { return em.createQuery(criteriaQuery); } @Override public <T> TypedQuery<T> createQuery(String qlString, Class<T> resultClass) { return em.createQuery(qlString, resultClass); } @Override public Query createNamedQuery(String name) { return em.createNamedQuery(name); } @Override public <T> TypedQuery<T> createNamedQuery(String name, Class<T> resultClass) { return em.createNamedQuery(name, resultClass); } @Override public Query createNativeQuery(String sqlString) { return em.createNativeQuery(sqlString); } @Override public Query createNativeQuery(String sqlString, @SuppressWarnings("rawtypes") Class resultClass) { return em.createNativeQuery(sqlString, resultClass); } @Override public Query createNativeQuery(String sqlString, String resultSetMapping) { return em.createNativeQuery(sqlString, resultSetMapping); } @Override public void joinTransaction() { em.joinTransaction(); } @Override public <T> T unwrap(Class<T> cls) { return em.unwrap(cls); } @Override public EntityManager getDelegate() { return em; } @Override public void close() { em.close(); } @Override public boolean isOpen() { return em.isOpen(); } @Override public EntityTransaction getTransaction() { return em.getTransaction(); } @Override public EntityManagerFactory getEntityManagerFactory() { return em.getEntityManagerFactory(); } @Override public CriteriaBuilder getCriteriaBuilder() { return em.getCriteriaBuilder(); } @Override public Metamodel getMetamodel() { return em.getMetamodel(); } } === DelegatingQuery.java public class DelegatingQuery implements Query { private Query delegate; public DelegatingQuery(Query delegate) { this.delegate = delegate; } public Query getDelegate() { return delegate; } @SuppressWarnings("rawtypes") public List getResultList() { return delegate.getResultList(); } public Object getSingleResult() { return delegate.getSingleResult(); } public int executeUpdate() { return delegate.executeUpdate(); } public Query setMaxResults(int maxResult) { return delegate.setMaxResults(maxResult); } public int getMaxResults() { return delegate.getMaxResults(); } public Query setFirstResult(int startPosition) { return delegate.setFirstResult(startPosition); } public int getFirstResult() { return delegate.getFirstResult(); } public Query setHint(String hintName, Object value) { return delegate.setHint(hintName, value); } public Map<String, Object> getHints() { return delegate.getHints(); } public <T> Query setParameter(Parameter<T> param, T value) { return delegate.setParameter(param, value); } public Query setParameter(Parameter<Calendar> param, Calendar value, TemporalType temporalType) { return delegate.setParameter(param, value, temporalType); } public Query setParameter(Parameter<Date> param, Date value, TemporalType temporalType) { return delegate.setParameter(param, value, temporalType); } public Query setParameter(String name, Object value) { return delegate.setParameter(name, value); } public Query setParameter(String name, Calendar value, TemporalType temporalType) { return delegate.setParameter(name, value, temporalType); } public Query setParameter(String name, Date value, TemporalType temporalType) { return delegate.setParameter(name, value, temporalType); } public Query setParameter(int position, Object value) { return delegate.setParameter(position, value); } public Query setParameter(int position, Calendar value, TemporalType temporalType) { return delegate.setParameter(position, value, temporalType); } public Query setParameter(int position, Date value, TemporalType temporalType) { return delegate.setParameter(position, value, temporalType); } public Set<Parameter<?>> getParameters() { return delegate.getParameters(); } public Parameter<?> getParameter(String name) { return delegate.getParameter(name); } public <T> Parameter<T> getParameter(String name, Class<T> type) { return delegate.getParameter(name, type); } public Parameter<?> getParameter(int position) { return delegate.getParameter(position); } public <T> Parameter<T> getParameter(int position, Class<T> type) { return delegate.getParameter(position, type); } public boolean isBound(Parameter<?> param) { return delegate.isBound(param); } public <T> T getParameterValue(Parameter<T> param) { return delegate.getParameterValue(param); } public Object getParameterValue(String name) { return delegate.getParameterValue(name); } public Object getParameterValue(int position) { return delegate.getParameterValue(position); } public Query setFlushMode(FlushModeType flushMode) { return delegate.setFlushMode(flushMode); } public FlushModeType getFlushMode() { return delegate.getFlushMode(); } public Query setLockMode(LockModeType lockMode) { return delegate.setLockMode(lockMode); } public LockModeType getLockMode() { return delegate.getLockMode(); } public <T> T unwrap(Class<T> cls) { return delegate.unwrap(cls); } } === DelegatingTypedQuery.java public class DelegatingTypedQuery<X> extends DelegatingQuery implements TypedQuery<X> { public DelegatingTypedQuery(TypedQuery<X> delegate) { super(delegate); } @SuppressWarnings("unchecked") public TypedQuery<X> getDelegate() { return (TypedQuery<X>) super.getDelegate(); } @Override public List<X> getResultList() { return getDelegate().getResultList(); } @Override public X getSingleResult() { return getDelegate().getSingleResult(); } @Override public TypedQuery<X> setMaxResults(int maxResult) { return getDelegate().setMaxResults(maxResult); } @Override public int executeUpdate() { return getDelegate().executeUpdate(); } @Override public TypedQuery<X> setFirstResult(int startPosition) { return getDelegate().setFirstResult(startPosition); } @Override public TypedQuery<X> setHint(String hintName, Object value) { return getDelegate().setHint(hintName, value); } @Override public int getMaxResults() { return getDelegate().getMaxResults(); } @Override public <T> TypedQuery<X> setParameter(Parameter<T> param, T value) { return getDelegate().setParameter(param, value); } @Override public int getFirstResult() { return getDelegate().getFirstResult(); } @Override public TypedQuery<X> setParameter(Parameter<Calendar> param, Calendar value, TemporalType temporalType) { return getDelegate().setParameter(param, value, temporalType); } @Override public TypedQuery<X> setParameter(Parameter<Date> param, Date value, TemporalType temporalType) { return getDelegate().setParameter(param, value, temporalType); } @Override public Map<String, Object> getHints() { return getDelegate().getHints(); } @Override public TypedQuery<X> setParameter(String name, Object value) { return getDelegate().setParameter(name, value); } @Override public TypedQuery<X> setParameter(String name, Calendar value, TemporalType temporalType) { return getDelegate().setParameter(name, value, temporalType); } @Override public TypedQuery<X> setParameter(String name, Date value, TemporalType temporalType) { return getDelegate().setParameter(name, value, temporalType); } @Override public TypedQuery<X> setParameter(int position, Object value) { return getDelegate().setParameter(position, value); } @Override public TypedQuery<X> setParameter(int position, Calendar value, TemporalType temporalType) { return getDelegate().setParameter(position, value, temporalType); } @Override public TypedQuery<X> setParameter(int position, Date value, TemporalType temporalType) { return getDelegate().setParameter(position, value, temporalType); } @Override public TypedQuery<X> setFlushMode(FlushModeType flushMode) { return getDelegate().setFlushMode(flushMode); } @Override public TypedQuery<X> setLockMode(LockModeType lockMode) { return getDelegate().setLockMode(lockMode); } @Override public Set<Parameter<?>> getParameters() { return getDelegate().getParameters(); } @Override public Parameter<?> getParameter(String name) { return getDelegate().getParameter(name); } @Override public <T> Parameter<T> getParameter(String name, Class<T> type) { return getDelegate().getParameter(name, type); } @Override public Parameter<?> getParameter(int position) { return getDelegate().getParameter(position); } @Override public <T> Parameter<T> getParameter(int position, Class<T> type) { return getDelegate().getParameter(position, type); } @Override public boolean isBound(Parameter<?> param) { return getDelegate().isBound(param); } @Override public <T> T getParameterValue(Parameter<T> param) { return getDelegate().getParameterValue(param); } @Override public Object getParameterValue(String name) { return getDelegate().getParameterValue(name); } @Override public Object getParameterValue(int position) { return getDelegate().getParameterValue(position); } @Override public FlushModeType getFlushMode() { return getDelegate().getFlushMode(); } @Override public LockModeType getLockMode() { return getDelegate().getLockMode(); } @Override public <T> T unwrap(Class<T> cls) { return getDelegate().unwrap(cls); } } ----- Mail original ----- De : Adrian Gonzalez <adr_gonza...@yahoo.fr> À : "users@openjpa.apache.org" <users@openjpa.apache.org> Cc : Envoyé le : Mercredi 23 janvier 2013 14h21 Objet : Re: Portable way to use query cache 1. After looking a little bit, I don't think we can use hint for query caching in OpenJPA. If this is confirmed, I'll open a JIRA for this. 2. Meanwhile, I've created this little utility [1] to do enable portable query caching. I've tested it only with Hibernate for the moment, but it should work with OpenJPA and toplink. To use it, just do : JpaUtils.cacheQuery(entityManager.createNamedQuery("myNamedQuery", Civilite.class)).getResultList(); 3. Perhaps there's a better approach - using a decorating entityManager, which decorates the query and intercepts setHint calls and call the appropriate API whenever the hint is "query.cache" (or sthing like that) : Then you'll just have to do : entityManager.createNamedQuery("myNamedQuery", Civilite.class).setHint("query.cache").getResultList(); With a CDI producer - or equivalent doing : @PersistenceContext private EntityManager em; @Produces public EntityManager getEntityManager () { return new EntityManagerDecorator(em); } WDYT ? [1] JpaUtils code : public final class JpaUtils { public static <X extends Query> X cacheQuery(X query) { return cacheQuery(query, true); } public static <X extends Query> X cacheQuery(X query, boolean cache) { String queryClassname = query.getClass().getName(); if (queryClassname.startsWith("org.hibernate")) { query.setHint("org.hibernate.cacheable", cache); } else if (queryClassname.startsWith("org.apache.openjpa")) { OpenJPAEntityManager oem = ((OpenJPAQuery<?>) query).getEntityManager(); OpenJPAEntityManagerFactory oemf = oem.getEntityManagerFactory(); QueryResultCache qcache = oemf.getQueryResultCache(); if (cache == true) { qcache.pin(query); } else { qcache.unpin(query); } } else if (queryClassname.startsWith("org.eclipse.persistence")) { query.setHint("eclipselink.query-results-cache", true); } return query; } } ----- Mail original ----- De : Adrian Gonzalez <adr_gonza...@yahoo.fr> À : "users@openjpa.apache.org" <users@openjpa.apache.org> Cc : Envoyé le : Mercredi 23 janvier 2013 10h38 Objet : Portable way to use query cache Hello, I'm a newbie with openJPA, I would like to know what's the best way to do query caching (in a JPA 2.x portable way). My webapp will run on JBoss 7.x (Hibernate) and Websphere 8 (OpenJPA). From , [1] there's some proprietary API involved. Is there a portable way, i.e. using hints instead [2]? Thanks ! [1] http://openjpa.apache.org/builds/2.0.1/apache-openjpa-2.0.1/docs/manual/main.html OpenJPAEntityManagerFactory oemf = OpenJPAPersistence.cast(emf); QueryResultCache qcache = oemf.getQueryResultCache(); [2] entityManager.createNamedQuery( NamedQueries.ETAT_CONTRAT_FIND_ALL, EtatContrat.class).setHint("openjpa.querycache", true);