iteye_3589 2009-06-11 11:13
浏览 252
已采纳

关于Rails中多表保存的事务一致性

[size=medium]关于Rails中多表操作的事务一致性[/size]

User has_one UserDetail 一个用户有一个用户明细,里面保存了用户的详细信息
User has_many MarkDetails 一个用户有多个积分明细,里面记录了每次获得积分的记录
Message 站内信

应用场景:
用户通过认证后,要更新一下users表中的是否通过验证的标志字段,同时更新一下用户明细表中的一些

信息,另外通过身份认证后,用户将得到100的积分,还要给用户发送一个站内认告诉他这件事情。

[code="ruby"]class User < ActiveRecord::Base

def confirmed_width_auth(id_card)
self.is_auth = 1
self.user_detail.id_card = id_card

mark_detail = self.mark_details.new
mark_detail.mark = 100
mark_detail.description = "身份认证得到积分"

message = Message.new
message.subject = "身份认证,得到积分"
message.body = "你得到100积分"
message.to_id = self.id

# 很明显,上面涉及到要保存三张表的信息,我应该接下来怎么处理 来保证事务的一致性呢?
self.save && mark_detail.save && message.save # 我这样做行不?
# 另外好像在关联的表,在Rails中是可以进行事务处理的,而没有关联的表好像不能进行事务处理的,是这样的吗?

end

end[/code]

在那个<[color=darkblue]应用Rails进行敏捷开发[/color]>的书上有讲到Rails中active record中的事务处理,不过那例子讲到的是在同一个表中不同的记录间所执行的操作,对于多个不同的表(甚至是没有任何关联的表),我们应该怎么来安全的处理事务呢?

因为我做的是一个电子商务方面的应用,所以对于业务操作中的事务还是非常关注的,[color=indigo]我希望能正确的安全的完成整个业务 方法的执行。[/color]

请有验证的和有想法的大大们指点一下,谢谢。
[b]问题补充:[/b]
谢谢nt,
[quote]1.捕捉异常。
2.数据库回滚,对象不回滚。(千万要记住) [/quote]
关于1是应该在controller中进行么?
关于2你想说什么?能具体 一点吗? :oops:
[b]问题补充:[/b]
[code="ruby"]
transaction do
self.save!
mark_detail.save!
message.save!
end
[/code]

我自己试了一下,以上的代码能正确工作,你为什么不用这样的代码呢?
比你刚才那圆环套圆环的方法好看一些啊。

我还是对 Rails的ar的事务处理机制不100%明白 :(
[b]问题补充:[/b]
我自己测试过的,数据库中相关表中的记录的事务能保证的,你可以试试,

不过你所说的
[color=red]非 User 对象应该无法回滚[/color]

是指user的实例 对象无法回滚到先前的状态吗?

  • 写回答

5条回答 默认 最新

  • xenocide 2009-06-11 18:23
    关注

    这个 transaction do ... end 其实是调用了 Uer 的类方法。
    而 User.transaction 只控制 user 表的回滚, 别的表它不管的。

    这个三环可以简化一下(最后一环其实没用到):
    [code="ruby"]
    User.transaction do
    MarkDetails.transaction do
    self.save!
    # 不过这一步可能连带保存了 mark_detail ?
    # 如果只生成一条 sql,就是单连接的事务,可以回滚 ……
    mark_detail.save!
    message.save!
    end
    end
    [/code]

    你用
    [code="ruby"]
    transaction do
    self.save!
    mark_detail.save!
    message.save!
    raise 'error'
    end
    [/code]
    试试看是不是都回滚了……

    参考 [url]http://api.rubyonrails.org/classes/ActiveRecord/Transactions/ClassMethods.html[/url]

    [quote]
    A transaction acts on a single database connection. If you have multiple class-specific databases, the transaction will not protect interaction among them. One workaround is to begin a transaction on each class whose models you alter: [/quote]

    transaction 是连接相关的,如果能保证只在一个数据库连接中做所有事情,应该一个套就够了,但是不一定保险 ……

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(4条)

报告相同问题?

悬赏问题

  • ¥15 NAO机器人的录音程序保存问题
  • ¥15 C#读写EXCEL文件,不同编译
  • ¥15 MapReduce结果输出到HBase,一直连接不上MySQL
  • ¥15 扩散模型sd.webui使用时报错“Nonetype”
  • ¥15 stm32流水灯+呼吸灯+外部中断按键
  • ¥15 将二维数组,按照假设的规定,如0/1/0 == "4",把对应列位置写成一个字符并打印输出该字符
  • ¥15 NX MCD仿真与博途通讯不了啥情况
  • ¥15 win11家庭中文版安装docker遇到Hyper-V启用失败解决办法整理
  • ¥15 gradio的web端页面格式不对的问题
  • ¥15 求大家看看Nonce如何配置