如何确保sqlite不缓存特定的选择查询?

时间:2009-08-21 18:12:36

标签: ruby-on-rails sqlite activerecord

我遇到的情况是我正在使用带有ActiveRecord和Rails的sqlite(同样,这是JRuby,所以我实际上使用的是jdbcsqlite适配器,以防万一)。现在,我正在尝试将一行插入表注册表中,但是只有在没有其他类似行的情况下。因此,

unless AttentionSeeker.find(:first, :conditions => {:key_id => key.id, :locale_id => l.id})
  item = AttentionSeeker.new(:key_id => key.id, :locale_id => l.id)
  item.save
end

这是日志中生成的输出:

CACHE (0.0ms)   SELECT * FROM attention_seekers WHERE (attention_seekers.key_id = 318 AND attention_seekers.locale_id = 20) 
AttentionSeeker Create (1.0ms)   INSERT INTO attention_seekers (key_id, locale_id) VALUES(318, 20)
CACHE (0.0ms)   SELECT * FROM attention_seekers WHERE (attention_seekers.key_id = 318 AND attention_seekers.locale_id = 20) 
AttentionSeeker Create (2.0ms)   INSERT INTO attention_seekers (key_id, locale_id) VALUES(318, 20)

正如您所看到的,由于某种原因,即使我插入影响它的元素,也会缓存查找。我做错了什么/如何阻止这种行为?

3 个答案:

答案 0 :(得分:3)

我做了一些挖掘并遇到this helpful blog post,提供了更多信息here。我的解决方案(使用Mike Buckbee建议的验证 - 谢谢!):

AttentionSeeker.uncached do
  item = AttentionSeeker.new(:key_id => key.id, :locale_id => l.id)
  item.save
end

答案 1 :(得分:1)

不是将此代码放在您的控制器中(我猜它是在哪里),您可能需要考虑使用验证,我认为这样可以解决问题:

class AttentionSeeker < ActiveRecord::Base
    validates_uniqueness_of :key_id, :scope => :locale_id
end

请注意验证规则中的“范围”选项。

如果不能尝试将查询包装在Transaction

如果失败了,这看起来非常混乱,你可以为查询本身添加一个缓存器。像

这样的东西
buster = rand(Time.now)
attention_seeker = AttentionSeeker.find(:first, :conditions => ["#{buster} = #{buster}"])

每次循环都会给你一个独特的查询。

答案 2 :(得分:0)

模式级别的唯一索引比validates_uniqueness_of更安全。

请参阅http://railswarts.blogspot.com/2007/11/validatesuniquenessof-is-broken-and.html

斯蒂芬