我在OpenJpa二级缓存中遇到了一些问题。大多数情况下,缓存是有效的,但在一个特定的情况下它不起作用。这是一个不工作的场景, 当您的代码结果为null值时,它会将其存储到缓存中,然后它永远不会清除该值。虽然它仅在查询返回值时清除值。
这是我为了从数据库中获取价值而编写的代码,
List<PartnerapiworkflowEntity> partnerapiworkflowEntityList = null;
try {
partnerapiworkflowEntityList = entityManager.createQuery("select p from someentity p where p.id = :Id and p.name = :name and " +
"p.code = :Code and p.operationname = :operationName")
.setParameter("Id", Id)
.setParameter("name", name)
.setParameter("code", Code)
.setParameter("operationName", operationName).getResultList();//.getSingleResult();
if(partnerapiworkflowEntityList != null && partnerapiworkflowEntityList.size() > 0){
return Boolean.TRUE;
}
} catch (NoResultException ne) {
logger.severe("some logging info.");
}
finally {
// entityManager.detach(partnerapiworkflowEntity);
}
这是一个刷新缓存的代码。
try{
entityManager.flush();
entityManager.clear();
entityManager.getEntityManagerFactory().getCache().evictAll();
//((JpaEntityManager)entityManager.getDelegate()).getServerSession().getIdentityMapAccessor().invalidateAll();
entityManager.flush();
} catch (Exception e){
throw e;
}
这是persistence.xml代码
<property name="openjpa.jdbc.DBDictionary" value="mysql"/>
<property name="openjpa.DataCache" value="true(EnableStatistics=true, CacheSize=10000, SoftReferenceSize=0, EvictionSchedule='+10')"/>
<property name="openjpa.QueryCache" value="true(EvictPolicy='timestamp')"/>
<!--<property name="openjpa.jdbc.QuerySQLCache" value="true(EnableStatistics=true)"/>-->
<property name="javax.persistence.sharedCache.mode" value="ENABLE_SELECTIVE"/>
<property name="openjpa.Instrumentation" value="jmx(Instrument='DataCache,QueryCache,QuerySQLCache')"/>
<property name="openjpa.MetaDataRepository" value="Preload=true"/>
<property name="openjpa.Log" value="SQL=Trace" />
<property name="openjpa.ConnectionFactoryProperties" value="PrintParameters=true" />
查询始终返回值时,一切正常。问题是它返回null值时开始。然后第一次存储在缓存中,然后它永远不会刷新。
我正在使用OpenJpa2和Hibernate。
答案 0 :(得分:3)
OpenJPA 2.2.2
首次发现此问题。在线查看显示,与L2缓存(https://issues.apache.org/jira/browse/OPENJPA-2285)
但是后来在https://issues.apache.org/jira/browse/OPENJPA-2522
中再次发现了这个问题目前尚未确定。但他们给出了一些绕过解决方案。
要禁用查询缓存(默认),请将openjpa.QueryCache
属性设置为false:
<property name="openjpa.QueryCache" value="false"/>
通过将sql query cache配置为false
指定自定义缓存类:
<property name="openjpa.jdbc.QuerySQLCache" value="com.mycompany.MyCustomCache"/>
使用非托管缓存:
<property name="openjpa.jdbc.QuerySQLCache" value="false"/>
OR
使用非托管缓存:
<property name="openjpa.jdbc.QuerySQLCache" value="all"/>
本教程描述了您的问题。在这里你可以得到 明确发生此错误的概念。
它提供了一个必须保留相关数据的解决方案。因此NullPointerException
不会出现。在OpenJPA无法解决问题之前,数据必须保持一致。 :d
用户应用程序可以通过在OpenJPA的EntityManager SPI接口上调用以下方法,在持久化上下文的整个生命周期内禁用Prepared SQL Cache:
OpenJPAEntityManagerSPI.setQuerySQLCache(boolean)
可以将插件属性openjpa.jdbc.QuerySQLCache
配置为
排除某些JPQL查询,如下所示。
<property name="openjpa.jdbc.QuerySQLCache" value="true(excludes='select c from Company c;select d from Department d')"/>
永远不会缓存JPQL查询select c from Company c
和select d from Department d
。
查询缓存存储查询执行返回的对象ID。运行查询时,JPA会组装一个密钥,该密钥基于查询属性和启动时使用的参数,并检查缓存的查询结果。如果找到一个,则查找缓存结果中的对象ID,并返回生成的持久性对象。否则,将针对数据库启动查询,并将查询加载的对象ID放入缓存中。在完全遍历在查询启动时返回的列表之前,不会缓存对象ID列表。
L2缓存会增加应用程序的内存消耗, 因此,限制L2缓存的大小很重要。有 也可能是群集中更新对象的陈旧数据 环境。为不经常读取配置L2缓存 修改后的实体建议不要经常使用L2缓存 同时更新的实体。
答案 1 :(得分:1)
您正在逐出条目,但查询缓存呢?可能是在正常情况下,查询案例会注意到驱逐,因此结果无效...这可以解释为什么null在这里失败。你能确认一下吗?
编辑:
<property name="openjpa.QueryCache" value="false"/>
表示没有查询缓存。我的坏。
其他尝试 - NULL检查?你有查询,用params - 你可以直接在数据库上执行它吗?