Rails - 乐观锁定总是触发StaleObjectError异常

5

我正在学习Rails,并阅读有关乐观锁的内容。我已经在我的articles表中添加了类型为integerlock_version列。

但是现在,每当我尝试第一次更新记录时,就会出现StaleObjectError异常。

这是我的迁移:

class AddLockVersionToArticle < ActiveRecord::Migration
  def change
    add_column :articles, :lock_version, :integer
  end
end

当我尝试通过Rails控制台更新文章时:

article = Article.first
=> #<Article id: 1, title: "Ccccc", text: "dfdsfsdfsdf", created_at: "2015-02-20 21:58:45", updated_at: "2015-02-25 20:03:12", lock_version: 0>

我可以:

article.title = "new title"
article.save

我得到了这个:

(0.3ms)  begin transaction
   (0.3ms)  UPDATE "articles" SET "title" = 'dwdwd', "updated_at" = '2015-02-25 20:40:36.537876', "lock_version" = 1 WHERE ("articles"."id" = 1 AND "articles"."lock_version" = 0)
   (0.1ms)  rollback transaction
ActiveRecord::StaleObjectError: Attempted to update a stale object: Article

1
也许这是默认设置,但锁定版本列在数据库中应该有一个默认值为0。 - Frederick Cheung
你确定这是你第一次做吗? - CodeGroover
@FrederickCheung lock_version 已经是 0。 - CodeGroover
1个回答

9

您需要将所有文章的lock_version初始化为0。 看一下这个查询:

UPDATE "articles" SET "title" = 'dwdwd', "updated_at" = '2015-02-25 20:40:36.537876', "lock_version" = 1 WHERE ("articles"."id" = 1 AND "articles"."lock_version" = 0)
       (0.1ms) 

如果查询返回0条记录更新,那么框架会认为您已经在另一个线程中更新了版本或删除了对象。

5
迁移应该是这样的:add_column :articles, :lock_version, :integer, default: 0, null: false - spickermann
我投反对票,lock_version 已经是0,在这个例子中,作者使用 bin/rails console。 - CodeGroover
4
据@CodeGroover表示,Rails Console显示lock_version的值为0。但是当我检查数据库时,它的值为空。将该列更改为具有默认值解决了问题。 - Rafael Adel

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接