如何在ColdFusion 2016中刷新单个查询缓存

时间:2017-06-27 17:38:36

标签: caching coldfusion refresh query-cache coldfusion-2016

我发现一段代码在ColdFusion 10引擎下工作,但不在ColdFusion 2016(CF12)引擎下。

我有一个CFC,其中包含被函数调用抓取的缓存查询。假设我有一个我想要缓存的查询,但是我对此查询使用的db表进行了更改。我没有看到返回的缓存查询中的数据,所以我需要刷新查询缓存,这很简单。这就是我设置代码的方式:

<cffunction name="getVariables" access="public" returntype="query">
    <cfargument name="time_span" required="true" default="#this.cacheSpan#" />
    <cfset var qryGetVariables="">

    <!--- IF REFRESH, NEW QRYTIMESPAN --->
    <cfif arguments.time_span eq 0 AND NOT this.bln_refresh>
        <!--- IF time_span 0 but not refresh, reset to original cache span --->
        <cfset arguments.time_span = this.cacheSpan />
    </cfif>
    <cfquery name="qryGetVariables" datasource="#this.dsn#" cachedwithin="#arguments.time_span#">
        select *
          from get_variables
         order by id, value
    </cfquery>
    <cfreturn qryGetVariables>
</cffunction>

我在同一个CFC中调用一个函数,以下列方式刷新此查询:

this.bln_refresh = true;
<cfinvoke method="getVariables" returnvariable="qryReturn">
   <cfinvokeargument name="time_span" value="0" />
</cfinvoke>
this.bln_refresh = false;

同样,这在ColdFusion 10之前有效,但现在它在ColdFusion 2016上不起作用。我需要做些什么来刷新这个特定查询的缓存?

3 个答案:

答案 0 :(得分:4)

是的,这在CF10之后发生了变化。 It's considered as bug, but it still not fixed.使用cachedWithin缓存查询结果后,使用createTimeSpan(0, 0, 0, 0)(等于0)或任何负值都无法使其无效。

演示

<!--- cache data for 10 minutes --->
<cfquery cachedWithin="#createTimeSpan(0, 0, 10, 0)#">
    SELECT `foo` FROM `example`;
</cfquery>

| FOO
| -----
| ABC

让我们改变数据。

UPDATE `example` SET `foo` = 'DEF';

正如所料......

<!--- invalidate cache and fetch new data --->
<cfquery cachedWithin="#createTimeSpan(0, 0, 0, 0)#">
    SELECT `foo` FROM `example`;
</cfquery>

| FOO
| -----
| DEF

现在让我们缓存最新的数据。

<!--- cache new data for 10 minutes --->
<cfquery cachedWithin="#createTimeSpan(0, 0, 10, 0)#">
    SELECT `foo` FROM `example`;
</cfquery>

CF10中的结果

| FOO
| -----
| DEF

cachedWithin <= 0使缓存的查询失效。因此,下一个cachedWithin > 0将新数据存储在缓存中。

CF2016中的结果

| FOO
| -----
| ABC

cachedWithin <= 0只是跳过了缓存。从缓存中提取下一个cachedWithin > 0。缓存没有变化。

更新

此错误的当前解决方法是使用cacheID的{​​{1}}属性,然后使用<cfquery>使其无效。

旧答案

您可以使用cacheRemove(theCacheID)无效查询缓存,会使所有缓存查询无效,这非常糟糕。另一个选项是使用cachePut自行缓存查询并使用cacheGet获取查询。

这是一个提示如何做到这一点。您可能需要在此处加入<cfobjectcache action="CLEAR">逻辑,我不确定它的目标是什么:

this.cacheSpan

答案 1 :(得分:1)

非常感谢@Alex,我遇到了以下似乎在我们的服务器上工作的解决方案:

<cffunction name="getVariables" access="public" returntype="query">
    <cfargument name="time_span" required="true" default="#this.cacheSpan#" />
    <cfset var qryGetVariables="" />
    <cfset var flt_qryTimeSpan=0>

    <cfif NOT cacheIdExists("qryGetVariablesCache") OR this.bln_refresh>
        <cfquery name="qryGetVariables" datasource="#this.dsn#" cachedwithin="#flt_qryTimeSpan#">
            select *
              from get_variables
             order by id, value
        </cfquery>
        <cfset cacheRemove("qryGetVariablesCache") />
        <cfset cachePut("qryGetVariablesCache",qryGetVariables,this.cacheSpan) />
    <cfelse>
        <cfset qryGetVariables = cacheGet("qryGetVariablesCache") />
    </cfif>
    <cfreturn qryGetVariables>

</cffunction>

答案 2 :(得分:0)

我不知道@Alex说的是否正确,但我没有理由怀疑他。我没有运行ColdFusion 2016.也许这是刷新特定查询缓存的另一个选项......

请记住,在使用cachedWithin标记的cfquery属性时,只有在满足以下所有条件时才会缓存查询。 “仅在管理员中启用查询缓存时才会生效。要使用缓存数据,当前查询必须使用相同的SQL语句,数据源,查询名称,用户名和密码。”({ {3}})

专注于这部分 - 相同的SQL语句。如果稍微更改SQL语句,则将刷新缓存。因此,您可以在SQL语句中添加另一个可用于刷新查询的条件。您甚至可以使用已经time_span的相同变量。

我在想这样的事情(语法可能因DBMS而异):

<cfquery name="qryGetVariables" datasource="#this.dsn#" cachedwithin="#arguments.time_span#">
    select *
    from get_variables
    where '#arguments.time_span#' = '#arguments.time_span#'
    order by id, value
</cfquery>

条件应始终为true,因此查询将返回相同的结果集。

*我没有测试过这个。