Laravel Eloquent ORM 거래


96

Eloquent ORM은 꽤 훌륭하지만, PDO와 같은 방식으로 innoDB를 사용하여 MySQL 트랜잭션을 설정하는 쉬운 방법이 있는지, 아니면 ORM을 확장해야 할 수 있는지 궁금합니다.

답변:


165

다음과 같이 할 수 있습니다.

DB::transaction(function() {
      //
});

Closure 내부의 모든 것은 트랜잭션 내에서 실행됩니다. 예외가 발생하면 자동으로 롤백됩니다.


1
클로저 내에서 클래스의 쿼리를 호출 할 수 있습니까? 작동할까요?
Rafael Soufraz

슬프게도 자신의 관련 방법으로 레코드를 저장하는 다른 모델의 인스턴스를 만드는 경우에는 작동하지 않습니다.
Volatil3 2015-08-28

트랜잭션 내에서 예외가 발생하면 (오류 메시지 생성 등), 롤백이 발생하도록 예외를 다시 내 보내야합니까?
alexw

3
좋은 답변이지만 몇 가지 사항이 있습니다. 1. "DB 사용"을 추가해야합니다. 예를 들어 모델 파일의 맨 위에서 2. JS와 달리 명시 적으로 전달하지 않는 한 상위 범위의 로컬 변수에 액세스 할 수 없습니다. 따라서 "use"구문을 추가해야합니다. DB :: transaction (function () use ($ user) {... $ user를 참조하는 물건 ...});
Polsonby

Discussed in more detail here링크가 죽었습니다.
tomloprod

100

익명 함수가 마음에 들지 않는 경우 :

try {
    DB::connection()->pdo->beginTransaction();
    // database queries here
    DB::connection()->pdo->commit();
} catch (\PDOException $e) {
    // Woopsy
    DB::connection()->pdo->rollBack();
}

업데이트 : laravel 4의 경우 pdo객체가 더 이상 공개되지 않으므로 :

try {
    DB::beginTransaction();
    // database queries here
    DB::commit();
} catch (\PDOException $e) {
    // Woopsy
    DB::rollBack();
}

15
바로 가기 방법 DB::beginTransaction()& DB::commit()&를 사용할 수도 있습니다 DB::rollback(). 그것은 조금 더 깨끗할 것입니다.
Flori

2
@Flori 제안을 사용하려면 업데이트하십시오. 깨끗합니다. 또한 새 답변을 위로 이동하면 답변이 덜 혼란스러워집니다. 두 번째 방법으로 돌아 오기 전에 첫 번째 방법을 사용했습니다.
frostymarvelous

이전 버전의 Laravel의 경우 다음이 필요할 수 있습니다.DB::connection()->getPdo()->beginTransaction();
대신

개인적으로 DB::transactionwith 콜백이 더 깨끗 하다고 생각 하지만 단점은 다른 예외에 대해 다른 핸들러를 지정해야하는 경우 try / catch 기술로 돌아 가야한다는 것입니다
OzzyTheGiant

33

Eloquent를 사용하고 싶다면 이것을 사용할 수도 있습니다.

이것은 내 프로젝트의 샘플 코드입니다.

        /* 
         * Saving Question
         */
        $question = new Question;
        $questionCategory = new QuestionCategory;

        /*
         * Insert new record for question
         */
        $question->title = $title;
        $question->user_id = Auth::user()->user_id;
        $question->description = $description;
        $question->time_post = date('Y-m-d H:i:s');

        if(Input::has('expiredtime'))
            $question->expired_time = Input::get('expiredtime');

        $questionCategory->category_id = $category;
        $questionCategory->time_added = date('Y-m-d H:i:s');

        DB::transaction(function() use ($question, $questionCategory) {

            $question->save();

            /*
             * insert new record for question category
             */
            $questionCategory->question_id = $question->id;
            $questionCategory->save();
        });

question->id트랜잭션 콜백 의 표현식은 0을 반환합니다.
Christos Papoulas

@ChristosPapoulas는 거래에서 자동 증분 ID를 얻을 수 없다는 뜻입니까?
hellojinjie

26

클로저를 피하고 싶고 파사드를 기꺼이 사용하고 싶다면 다음은 일을 멋지고 깨끗하게 유지합니다.

try {
    \DB::beginTransaction();

    $user = \Auth::user();
    $user->fill($request->all());
    $user->push();

    \DB::commit();

} catch (Throwable $e) {
    \DB::rollback();
}

명령문이 실패하면 커밋이 적중되지 않고 트랜잭션이 처리되지 않습니다.


문이 실패하면 후속 문이 실행되지 않습니다. 여전히 트랜잭션을 명시 적으로 롤백해야합니다.
제이슨

1
@Jason 답변을 업데이트했습니다. 대부분의 (모든?) 데이터베이스 엔진에서 커밋되지 않은 트랜잭션 쿼리는 커밋되지 않을 때 연결이 종료 될 때 두 가지를 염두에두고있었습니다. 그러나, 나는 당신이 무슨 말을 동의, 그리고 아마도 가장 명시 적으로
크리스

18

나는 당신이 클로저 솔루션을 찾고 있지 않다는 것을 확신합니다. 더 컴팩트 한 솔루션을 위해 이것을 시도하십시오.

 try{
    DB::beginTransaction();

    /*
     * Your DB code
     * */

    DB::commit();
}catch(\Exception $e){
    DB::rollback();
}

10

어떤 이유로 어디서든이 정보를 찾기가 매우 어려웠 기 때문에 Eloquent 트랜잭션과 관련된 내 문제가 정확히 이것을 바꾸고 있었기 때문에 여기에 게시하기로 결정했습니다.

stackoverflow 답변을 읽은 후 데이터베이스 테이블이 InnoDB 대신 MyISAM을 사용하고 있음을 깨달았습니다.

트랜잭션이 Laravel (또는 보이는 다른 곳)에서 작동하려면 테이블이 InnoDB를 사용하도록 설정되어 있어야합니다.

왜?

MySQL 트랜잭션 및 원자 작업 문서 인용 ( 여기 ) :

MySQL Server (버전 3.23-max 및 모든 버전 4.0 이상)는 InnoDB 및 BDB 트랜잭션 스토리지 엔진과의 트랜잭션을 지원합니다. InnoDB는 완전한 ACID 준수를 제공합니다. 14 장, 스토리지 엔진을 참조하십시오. 트랜잭션 오류 처리와 관련하여 표준 SQL과 InnoDB의 차이점에 대한 자세한 내용은 14.2.11 절,“InnoDB 오류 처리”를 참조하십시오.

MySQL Server의 다른 비 트랜잭션 스토리지 엔진 (예 : MyISAM)은 "원자 적 작업"이라는 데이터 무결성에 대한 다른 패러다임을 따릅니다. 트랜잭션 측면에서 MyISAM 테이블은 효과적으로 항상 autocommit = 1 모드에서 작동합니다. 원자 적 작업은 종종 더 높은 성능과 비슷한 무결성을 제공합니다.

MySQL Server는 두 가지 패러다임을 모두 지원하므로 원자 적 작업의 속도 또는 트랜잭션 기능의 사용 중 애플리케이션이 최상의 서비스를 제공하는지 결정할 수 있습니다. 이 선택은 테이블별로 할 수 있습니다.


이것은 DML에 해당되며 DDL에 항상 해당되는 것은 아닙니다.
Yevgeniy Afanasyev 2015

4

예외가 발생하면 트랜잭션이 자동으로 롤백됩니다.

라 라벨 기본 거래 형식

    try{
    DB::beginTransaction();

    /* 
    * SQL operation one 
    * SQL operation two
    ..................     
    ..................     
    * SQL operation n */


    DB::commit();
   /* Transaction successful. */
}catch(\Exception $e){       

    DB::rollback();
    /* Transaction failed. */
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.