浏览 3717 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2007-06-21
1,Rails默认将父子关系的表的save()和destroy()包装在一个事务里(见AWDWR一书的Transactions) 这保证了父子保存和删除的原子性,即ActiveRecord是级联保存和级联删除的,有源码为证 transactions.rb: module ActiveRecord module Transactions def self.included(base) base.extend(ClassMethods) base.class_eval do [:destroy, :save, :save!].each do |method| alias_method_chain method, :transactions end end end module ClassMethods def transaction(*objects, &block) previous_handler = trap('TERM') { raise TransactionError, "Transaction aborted" } increment_open_transactions begin unless objects.empty? ActiveSupport::Deprecation.warn "Object transactions are deprecated and will be removed from Rails 2.0. See http://www.rubyonrails.org/deprecation for details.", caller objects.each { |o| o.extend(Transaction::Simple) } objects.each { |o| o.start_transaction } end result = connection.transaction(Thread.current['start_db_transaction'], &block) objects.each { |o| o.commit_transaction } return result rescue Exception => object_transaction_rollback objects.each { |o| o.abort_transaction } raise ensure decrement_open_transactions trap('TERM', previous_handler) end end private def increment_open_transactions #:nodoc: open = Thread.current['open_transactions'] ||= 0 Thread.current['start_db_transaction'] = open.zero? Thread.current['open_transactions'] = open + 1 end def decrement_open_transactions #:nodoc: Thread.current['open_transactions'] -= 1 end end def transaction(*objects, &block) self.class.transaction(*objects, &block) end end end mysql_adapter.rb: module ActiveRecord module ConnectionAdapters class MysqlAdapter < AbstractAdapter def begin_db_transaction #:nodoc: execute "BEGIN" rescue Exception # Transactions aren't supported end def commit_db_transaction #:nodoc: execute "COMMIT" rescue Exception # Transactions aren't supported end def rollback_db_transaction #:nodoc: execute "ROLLBACK" rescue Exception # Transactions aren't supported end end end end 如果我们想给自定义的方法添加事务控制,有如下三种情况: 1,block transaction def some_method transaction do david.withdrawal(100) mary.deposit(100) end end transaction方法后的block里的操作保持原子性 2,Object-level transaction def some_method Account.transaction(from, to) do from.withdraw(100) to.deposit(100) end end 这种情况下不仅数据库表有事务回滚,对象状态也有事务回滚 不过现在Rails去掉object transactions 如果你仍然想使用object transactions,可以使用object_transactions插件 3,Across database connections def some_method Student.transaction do Course.transaction do course.enroll(student) student.units += course.units end end end 但是这样做很难保证不同表的状态,ActiveRecord也不打算做multiple database的transaction,建议不要使用这种方式 我们再看看用到transactions的一些地方 association_collection.rb: module ActiveRecord module Associations class AssociationCollection < AssociationProxy def <<(*records) result = true load_target @owner.transaction do flatten_deeper(records).each do |record| raise_on_type_mismatch(record) callback(:before_add, record) result &&= insert_record(record) unless @owner.new_record? @target << record callback(:after_add, record) end end result && self end end end end has_many_through_association.rb: module ActiveRecord module Associations class HasManyThroughAssociation < AssociationProxy def create!(attrs = nil) @reflection.klass.transaction do self << @reflection.klass.with_scope(:create => attrs) { @reflection.klass.create! } end end end end end 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |