Rails的事务,通过异常来决定是否需要回滚,其中抛出ActiveRecord::Rollback异常将只回滚,不抛出异常。
假如是嵌套事务,例如:
begin ActiveRecord::Base.transaction do User.create(:name => "java") ActiveRecord::Base.transaction do User.create(:name => "c#") #raise "抛出异常==!" raise ActiveRecord::Rollback end end rescue => e puts "输出异常信息, #{e.message}" end
两条记录都会插入,子事务的语句会被合并到父事务,由于并未引发异常,导致两条记录都被插入。
再比如:
begin ActiveRecord::Base.transaction do User.create(:name => "java") ActiveRecord::Base.transaction do User.create(:name => "c#") raise "抛出异常==!" #raise ActiveRecord::Rollback end end rescue => e puts "输出异常信息, #{e.message}" end
两条记录都不会被插入,都会回滚,虽然子事务被合并到父事务中,单抛出异常,导致父事务被回滚。
transaction类方法,有一个requires_new的参数,当这个参数为true,子事务语句不会合并到父事务中,当抛出异常,子事务回滚,异常向上传递,导致父事务也会回滚。不过,如果子事务使用raise ActiveRecord::Rollback,子事务只会混滚到事务记录点,即子事务回滚,父事务继续执行,例如:
begin ActiveRecord::Base.transaction do User.create(:name => "java") ActiveRecord::Base.transaction do User.create(:name => "c#") raise ActiveRecord::Rollback end end rescue => e puts "输出异常信息, #{e.message}" end
第一条记录会被插入,而第二条被回滚了。