在空值的情况下,OpenJpa查询缓存不会刷新

时间:2016-04-15 09:04:09

标签: java spring performance hibernate openjpa

我在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。

2 个答案:

答案 0 :(得分:3)

OpenJPA 2.2.2首次发现此问题。在线查看显示,与L2缓存(https://issues.apache.org/jira/browse/OPENJPA-2285

相关的主干上修复了一个缺陷

但是后来在https://issues.apache.org/jira/browse/OPENJPA-2522

中再次发现了这个问题

解决方案:

目前尚未确定。但他们给出了一些绕过解决方案。

  1. 禁用查询缓存
  2. 要禁用查询缓存(默认),请将openjpa.QueryCache属性设置为false:

    <property name="openjpa.QueryCache" value="false"/>
    
    1. 通过将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"/>

      1. Open JPA - L2 Cache Issue and Workaround
      2.   

        本教程描述了您的问题。在这里你可以得到   明确发生此错误的概念。

        它提供了一个必须保留相关数据的解决方案。因此NullPointerException不会出现。在OpenJPA无法解决问题之前,数据必须保持一致。 :d

        1. Several mechanisms are available to the application to bypass SQL caching for a JPQL query.
        2. 用户应用程序可以通过在OpenJPA的EntityManager SPI接口上调用以下方法,在持久化上下文的整个生命周期内禁用Prepared SQL Cache:

          OpenJPAEntityManagerSPI.setQuerySQLCache(boolean) 
          
          1. 可以将插件属性openjpa.jdbc.QuerySQLCache配置为 排除某些JPQL查询,如下所示。

            <property name="openjpa.jdbc.QuerySQLCache" value="true(excludes='select c from Company c;select d from Department d')"/>

          2. 永远不会缓存JPQL查询select c from Company cselect d from Department d

            Root Cause Analysis:

            查询缓存存储查询执行返回的对象ID。运行查询时,JPA会组装一个密钥,该密钥基于查询属性和启动时使用的参数,并检查缓存的查询结果。如果找到一个,则查找缓存结果中的对象ID,并返回生成的持久性对象。否则,将针对数据库启动查询,并将查询加载的对象ID放入缓存中。在完全遍历在查询启动时返回的列表之前,不会缓存对象ID列表。

            IBM Recommendation:

              

            L2缓存会增加应用程序的内存消耗,   因此,限制L2缓存的大小很重要。有   也可能是群集中更新对象的陈旧数据   环境。为不经常读取配置L2缓存   修改后的实体建议不要经常使用L2缓存   同时更新的实体。

            资源链接:

            Open JPA 2.4.0 Caching Reference Guide

答案 1 :(得分:1)

您正在逐出条目,但查询缓存呢?可能是在正常情况下,查询案例会注意到驱逐,因此结果无效...这可以解释为什么null在这里失败。你能确认一下吗?

编辑:

<property name="openjpa.QueryCache" value="false"/>

表示没有查询缓存。我的坏。

其他尝试 - NULL检查?你有查询,用params - 你可以直接在数据库上执行它吗?