2012-04-24 1 views
4

TL : DR : AR :: Base 저장 트랜잭션 내에 중복 조인 테이블 레코드를 삽입하면 (고유 제한 조건으로 인해) 저장이 실패하고 롤백되는 원인이됩니다. 복제 조인 테이블 레코드를 추가하지 않아도됩니다. 저장하지 않는 것이 좋지 않습니다.postgres 데이터베이스 오류로 인해 트랜잭션 재시작이 발생합니다.

class EventsSeries < ActiveRecord::Base 
    # UNIQUE KEY `index_events_series_on_event_id_and_series_id` (`event_id`,`series_id`) 
    belongs_to :event 
    belongs_to :series 
end 

class Series < ActiveRecord::Base 

    has_many :events_series 
    before_validation :add_new_event 

private 

    def add_new_event 
    # boils down to something like this 
    EventSeries.new.tap do |es| 
     es.event_id = 1 
     es.series_id = 1 
     begin 
     es.save! 
     rescue ActiveRecord::RecordNotUnique 
     # Great it exists 
     # this isn't really a problem 
     # please move on 
     end 
    end 
    end 
end 

호출 : 나는 포스트 그레스에 MySQL의 응용 프로그램을 마이그레이션하고있어


은 ... 나는 DB 조인 테이블 레코드를 추가 mysql을-땅에서이 같은 패턴 무언가를 수행하는 데 사용 이런 식으로 :

Series.first.save 
# should not blow up on duplicate join record, cause i don't care 

그러나이 경우 포스트그레스가 폭발합니다. 중복 레코드를 삽입 원인은

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

에 ... "예외 처리 및 롤백"섹션

는 기본적으로 트랜잭션을 #save 시작 (경고 참조), 그리고 :이 여기에 좋은 설명이다 # save의 트랜잭션을 무효화하는 데이터베이스 예외 (sadface)입니다.

포스트 그레스 랜드에서 사용할 수있는 더 좋은 패턴이 있습니까?

감사합니다.


편집 :

나는 단단히 '은 시리즈 내에서이 논리를 유지 패턴은 다음과 같습니다 ... 트랜잭션을 저장하는 것이 합리적 생각

:

s = Series.new 
s.new_event_id = 123 # this is just an attr_accessor 
s.save # callbacks on Series know how to add the new event. 

... 내 수 컨트롤러는 매우 작습니다.

+0

SELECT ... 쉐어가 마음에 와서 그것이 이미 있는지 확인합니다. 가능한 중복 데이터에 대해 수행 한 작업은 각 INSERT를 개별 트랜잭션으로 만드는 것입니다. – freeone3000

+0

맞다. 그렇지만 내 논리가 저장 호출의 내부에 멋지게 싸여 질 수는 없다. – jsharpe

+0

ActiveRecord는 savepoint와 같은 PostgreSQL 서브 트랜잭션에 액세스 할 수있는 방법을 제공합니까? plpgsql의 http://www.postgresql.org/docs/current/interactive/sql-savepoint.html ... 또는 EXCEPTION 절? http://www.postgresql.org/docs/current/interactive/plpgsql-control-structures.html#PLPGSQL-ERROR-TRAPPING – kgrittn

답변

3

트랜잭션 내에 있고 오류를 복구하고 전체 트랜잭션을 무효화하지 않는 경우 세이브 포인트를 사용해야합니다.

명령 SAVEPOINT 일부 라벨을 사용하면 나중에 오류를 포함하여 (트랜잭션에 그 상태로 돌아가 저장 점을 찍은 후 모든 작업을 무시하는 일부 라벨을 SAVEPOINT 명령을 ROLLBACK을 실행할 수 있습니다).

더 자세한 설명은 내 다른 답변 Continuing a transaction after primary key violation error을 참조하십시오.

+0

굉장합니다. 너는 영웅이다. 다른 사람을 위해 : 확실히이 답변에서 위의 링크를 참조하십시오. – jsharpe

관련 문제