2011-09-16 6 views
2

YAML 파일에 저장된 SQL 문 (업데이트, 삽입 및 삭제)을 실행하는 클래스가 있습니다. 나는 모든 진술을 하나의 거래에 포함시키고 자한다. SQL 문 중 하나라도 실패하면 롤백됩니다. 모든 명령문이 성공하면 커밋됩니다. MySQL 데이터베이스에 연결하고 있습니다. 여기 내 코드는 다음과 같습니다.Ruby DataMapper에서 트랜잭션을 어떻게 활용할 수 있습니까?

require 'dm-core' 

class SqlExecuter 

    def initialize(input_yaml_file_name) 
    @input_yaml_file_name = input_yaml_file_name 
    @adapter = DataMapper.repository(:default).adapter 
    @sql_statements = YAML::load(File.open(input_yaml_file_name)) 
    end 

    def execute() 
    puts "Executing SQL statements in #{@input_yaml_file_name} file...." 

    @sql_statements.each do | sql_statement | 
     @adapter.execute(sql_statement) 
    end 
    end 
end # class SqlExecuter 

나는 모든 @ adapter.execute 호출을 하나의 트랜잭션으로 포함하고 싶습니다. dm-transactions 젬의 코드를 살펴 봤지만이 컨텍스트에서이 코드를 사용하는 방법을 알 수는 없습니다. 오류가 발생하면이 트랜잭션과 롤백에 SQL 문을 구현하는

+2

나만인가, 아니면'dm-transactions'에 대한 문서가 전혀 없습니까? 나는 확실히 그것을 발견 할 수 없다. – fennec

답변

5

사용 :

require 'dm-transactions' 
YourModel.transaction do |t| 
    begin 
    @sql_statements.each do |sql_statement| 
     DataMapper.repository(:default).adapter.execute(sql_statement) 
    end 
    rescue DataObjects::Error 
    t.rollback 
    end 
end 

Using transactions with Ruby DataMapper에서 봐, 그리고 dm-transactions_spec.rb

+0

나의 임의의 SQL 문이 YourModel과 관계가있는 테이블을 포함하고 있다면, 위의 내용이 저에게 효과적 일 것입니다. 감사. – programmingfun11

0

임 원리는 응답은 여전히 ​​올바른 것입니다. User.transaction은 모델 "User"가 첨부 된 저장소 (데이터베이스)에서 트랜잭션을 엽니 다. 보다 일반적인 방법은 지금까지 내가 말할 수있는

DataMapper.repository(:default).transaction do |t| 
    t.commit 
end 
+1

이상하게도 sql_statements.each 블록 내부의 모든 내용이 무시됩니다. 는'데프()' '풋 실행 "#에서 SQL 문 실행을 {@ input_yaml_file_name} 파일 .... \ n"' 'DataMapper.repository (기본적) .transaction가 할 | t |' 을 'begin' '@sql_statements.each do | sql_statement | 'adapter.execute (sql_statement)' '끝' 'rescue' = @ '결과는 't.rollback' ' '끝' '끝 번호의 execute' 당신은 아마 당신의 커밋해야합니다 – programmingfun11

+1

을 end' 블록 내부의 트랜잭션 :) – Xylakant

+0

블록 안에 t.commit을 추가했지만 @ sql_statements.each의 모든 내용은 여전히 ​​무시되었습니다. – programmingfun11

4

, 당신은 더 이상 롤백 트랜잭션에 대한 rollback()를 호출 할 필요가 없습니다. 당신은 단지과 같이, 트랜잭션 블록 묶어야해야합니다

YourModel.transaction do 
    @sql_statements.each do |sql_statement| 
    DataMapper.repository(:default).adapter.execute(sql_statement) 
    end 
end 

이 적어도, 즉 내가 읽은 방법 년대 dm-transactions spec about rollbacks :

it 'should rollback when an error is raised in a transaction' do 
    @user_model.all.size.should == 0 
    lambda { 
    @user_model.transaction do 
     @user_model.create(:name => 'carllerche') 
     raise 'I love coffee' 
    end 
    }.should raise_error('I love coffee') 
    @user_model.all.size.should == 0 
end 

내가 많이 DataMapper를 사용하여 상당한 응용 프로그램을 작성했습니다 트랜잭션이없고 rollback()을 사용하지 않고 실패한 모든 트랜잭션이 항상 롤백됩니다.

또한 AR (ActiveRecord)을 사용한 이후 1 년이 지났음을 기억하면 DataMapper 트랜잭션 동작이 AR 동작을 모방합니다.

관련 문제