0 0

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

关于Rails中多表操作的事务一致性

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

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

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

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


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

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

请有验证的和有想法的大大们指点一下,谢谢。
问题补充:
谢谢nt,
引用
1.捕捉异常。
2.数据库回滚,对象不回滚。(千万要记住)

关于1是应该在controller中进行么?
关于2你想说什么?能具体 一点吗?
问题补充:
transaction do
      self.save!
      mark_detail.save!
      message.save!
    end


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

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

不过你所说的
非 User 对象应该无法回滚

是指user的实例 对象无法回滚到先前的状态吗?
2009年6月11日 11:13

5个答案 按时间排序 按投票排序

0 0

采纳的答案

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

这个三环可以简化一下(最后一环其实没用到):

User.transaction do
  MarkDetails.transaction do
    self.save!
    # 不过这一步可能连带保存了 mark_detail ?
    # 如果只生成一条 sql,就是单连接的事务,可以回滚 ……
    mark_detail.save!
    message.save!
  end
end 


你用
transaction do
  self.save!
  mark_detail.save!
  message.save!
  raise 'error'
end

试试看是不是都回滚了……

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

引用

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:


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

2009年6月11日 18:23
0 0

不对…… 你这个等于

User.transaction do
  ...
end

非 User 对象应该无法回滚

2009年6月11日 17:40
0 0

在 controller 和 model 都可以。如果不打算提供过于具体的出错信息,甚至可以写个处理异常的 filter,一次搞定。


第二条,考虑这个情况:
第一步保存了 user,第二步保存 mark_detail 出错,那么第一步保存的 user 记录会回滚消失。但这个回滚是数据库做的,回滚了什么东西 rails 不知道,所以 user 对象还是刚 save 时的状态,甚至还有一个子虚乌有的 id 属性…… 要继续使用这个对象,得注意这点。

2009年6月11日 17:11
0 0

更正: MarkDetails --> MarkDetail

还有一点设计上的: 这个东西涉及到多个类,万一 User 膨胀到很大很大(我说的是万一……),分离出 Service 类好点。

2009年6月11日 16:40
0 0

User.transaction do
  MarkDetails.transaction do
    Message.transaction do
      self.save!
      mark_detail.save!
      message.save!
    end
  end
end

save! 是异常版,如果其中出了异常,三张表都回滚。

另外要注意的:
1.捕捉异常。
2.数据库回滚,对象不回滚。(千万要记住)

2009年6月11日 16:37

相关推荐

    rails敏捷开发的购物车系统

    在本文中,我们将深入探讨如何使用Rails敏捷开发技术构建一个购物车系统,特别是在参考《rails敏捷开发第四版》中的示例。Rails 3.2.6是本文的基础框架,它是一个强大的Ruby Web应用程序框架,以其MVC(模型-视图-...

    Pro ActiveRecord Databases with Ruby and Rails.pdf

    3. **事务管理**: 自动处理数据库事务,确保数据的一致性和完整性。 4. **关联关系**: 支持多种关联关系,如一对一、一对多等,简化了复杂数据结构的处理。 5. **迁移系统**: 内置了迁移系统,可以方便地进行数据库...

    Pro Active Record. Databases with Ruby and Rails

    3. **验证与回调**:掌握模型验证,确保数据的完整性和一致性,同时理解回调机制,如before_save、after_create等,以便在数据保存前后执行特定操作。 4. **关联**:深入研究Active Record的各种关联类型,如has_...

    Rails应用程序中同时修改操作冲突问题的解决方案

    Rails应用程序中的操作冲突问题是指当多个用户或进程尝试同时修改...总之,Rails的乐观锁机制提供了一种轻量级的方法来处理并解决同时修改数据导致的冲突问题,使得程序能够在多用户环境下保持数据的一致性和完整性。

    TestingRailsApps

    - 在测试生命周期中,Rails会自动处理数据库的事务回滚,确保每次测试前后数据库状态一致。 - 数据库操作通常包括开始事务、插入测试数据、执行测试、回滚事务等步骤。 #### 结论 通过对"TestingRailsApps" PPT的...

    active_rails_examples

    这对于保持数据一致性至关重要。 9. **动态Finder**: 动态Finder允许根据条件快速查找记录,如`User.find_by_email("john@example.com")`。 10. **更新记录(Updating Records)**: 可以通过`update`或`update_all...

    rails-garden-manager

    `Gemfile` 定义了应用需要的外部 gem(Ruby 包),而 `Gemfile.lock` 记录了具体的 gem 版本,确保在不同环境中的一致性。 9. **Assets**:`app/assets` 目录包含 CSS、JavaScript 和图像等前端资源,Rails 使用 ...

    timeservice:一种简单的EE服务,现在可以在事务中保持不变

    这是事务一致性的重要保证,防止因时钟漂移导致的不一致结果。例如,在金融交易系统中,确保交易时间的一致性对于避免纠纷至关重要。 Ruby是一种动态、面向对象的编程语言,以其简洁的语法和强大的元编程能力而闻名...

    Castle ActiveRecord 手册

    5. **事务管理**:Castle ActiveRecord支持自动事务管理,可以在方法级别或块级别开启和提交事务,确保数据一致性。你可以使用`NHibernate.ISession`的`BeginTransaction`、`Commit`和`Rollback`方法来控制事务。 6...

    ActiveRecord简单实例代码.zip

    在模型中,你可以添加验证规则来确保数据的完整性和一致性。例如,`validates :email, presence: true, format: { with: /\A[\w+\-.]+@[a-z\d\-]+(\.[a-z\d\-]+)*\.[a-z]+\z/i }`会验证电子邮件字段是否为空以及...

    Ruby-Rein让ActiveRecord支持数据库约束

    标题 "Ruby-Rein让ActiveRecord支持数据库约束" 暗示了一个关于Ruby开发中的一个库,名为Rein,它的目标是增强ActiveRecord的功能,使其能够更好地处理数据库约束。ActiveRecord是Ruby on Rails框架中用于对象关系...

    Ruby-ActiveRecord的BiTemporal数据模型

    5. **事务处理**:确保在处理BiTemporal模型时,事务管理和回滚是正确的,以保持数据一致性。 通过这种方式,Ruby开发者可以在Rails应用中实现强大的BiTemporal数据管理,为业务提供更高级别的数据完整性和可追溯性...

    activejdbc,ActuvJDBC是一种快速而精简的Java ORM.zip

    这使得在执行一系列数据库操作时确保数据的一致性和完整性。 在实际应用中,ActiveJDBC 提供了一个自动的模型发现机制,能够扫描指定的包或类路径,找到所有的模型类,并自动建立与数据库的映射关系。这样,无需...

    GORM_ADO数据库操作模块.rar

    4. **事务处理**:在需要保证数据一致性的操作中,事务是非常重要的。GORM_ADO模块通过`withTransaction`方法来包裹一组操作,确保它们要么全部成功,要么全部回滚。 5. **错误处理**:在数据库操作过程中,可能会...

    record_store

    4. **事务处理**:在处理多个操作时,如同时更新多条记录,`record_store`可能支持事务,确保数据的一致性和完整性。 5. **错误处理**:良好的记录存储系统会处理可能出现的异常情况,如数据库连接问题或数据验证...

Global site tag (gtag.js) - Google Analytics