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

问题描述 投票:4回答:2

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

java spring performance hibernate openjpa
2个回答
3
投票

这个问题首先在OpenJPA 2.2.2上观察到。在线查看显示,在二级缓存(https://issues.apache.org/jira/browse/OPENJPA-2285)相关的主干上修复了一个缺陷

但是后来在https://issues.apache.org/jira/browse/OPENJPA-2522再次发现了这个问题


解:

到目前为止还没有修复。但他们给出了一些绕过解决方案。

  1. 禁用查询缓存

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

<property name="openjpa.QueryCache" value="false"/>
  1. 通过将sql查询缓存配置为false 要指定自定义缓存类: <property name="openjpa.jdbc.QuerySQLCache" value="com.mycompany.MyCustomCache"/> 要使用非托管缓存: <property name="openjpa.jdbc.QuerySQLCache" value="false"/> 要么 要使用非托管缓存: <property name="openjpa.jdbc.QuerySQLCache" value="all"/>

  1. Open JPA - L2 Cache Issue and Workaround

本教程描述了您的问题相同。在这里,您可以获得发生此错误的清晰概念。

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


  1. Several mechanisms are available to the application to bypass SQL caching for a JPQL query.

通过在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')"/>

永远不会缓存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
投票

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

编辑:

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

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

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

© www.soinside.com 2019 - 2024. All rights reserved.