2017-04-04 9 views
0

データベースに値を変更し、ファイルシステム上でいくつかの操作を行ういくつかのメソッドを記述する必要があります。データベースにtrueにブールUpdatingフィールドを設定しいくつかの操作とロールバックを伴うトランザクションの処理

  1. : は、だから私はステップのこのシーケンスを確認する必要があります。この値にリンクされているファイルシステムおよびデータベース情報へのアクセスを避けるために使用されます(たとえば車の艦隊)
  2. データベースで何らかの操作を行います。たとえば、日付、名前、値、またはその他のフィールドを変更します。これらの変更は、より多くのデータベーステーブルに影響します。
  3. あなたは、私がエラーを管理し、データベースやファイルシステムを復元するために、ロールバックの手順を開始する必要が想像できるように、偽

にブール値Updatingを設定し、ファイルシステムへの変更およびデータベース

  • してください。 私の方法を書く方法について疑問があります。私が持っている:

    • エンティティ
    • JpaRepositoryを拡張し、それらをデータベースに書き込む場合@Transactionalアノテーションを付けるメソッド名と@Queryからクエリの作成を持っているリポジトリのインターフェース(そうでない場合、私はエラーをrecevied)
    • サービス・インターフェース
    • データベースに簡単な変更を加えるためのすべてのメソッドを含むサービス実装。このクラスは、私がデータベースを使用するサービスのメソッドを呼び出すが、私はこれらのメソッドの一部を呼び出した場合、ロールバックをスローすることはできませんので、私はデータベースに各値を書き込み、他のクラスから@Transactional

    、またはI間違ったと注釈されています? ステップ1はデータベースに直接書き込む必要がありますが、代わりに@Transactionalプロパティを使用する必要がありますが、メソッドに@Transactionalを追加するだけで十分ですか?ファイルシステムのロールバックでは、すべてのサブフォルダのバックアップを作成し、エラーが発生した場合に復元します。たとえば :

    @Transactional(rollbackFor=FileSystemException.class) 
    private void changeDisplacement(int idApplication, int idDisplacement){ 
        applicationServices.setUpdating(true); //this has be to write immediatly into database so that the other methods can stop using this application 
        Application application = applicationServices.getId(idApplication); 
        application.setDisplacement(displacementServices.getId(idDisplacement)); 
    
        //OTHER OPERATIONS ON DIFFERENT TABLES 
    
        //OPERATIONS ON FILE SYSTEM CATCHING ALL EXCEPTION WITH TRY-CATCH AND IN THE CATCH RESTORE FILESYSTEM AND THROW FileSystemException to start database rollback 
        //In the finally clause use applicationServices.setUpdating(false) 
    } 
    

    が、それはこのロジックで動作することができますか@Transactionalフィールドがここで間違っていますか? ありがとう

  • +0

    私はあなたが_FILE RESTORE_フェーズを保証できないと思います。ファイルを書き込んでいる間に例外がスローされると、それを書き直して状態を復元する可能性が高くなります。 – minus

    +0

    確かに、私は一度だけ更新しようとします。復元が失敗した場合、私は電子メールを送信し、手動操作で問題が解決されるまでファイルシステムをロックしたままにしておきます。 – luca

    答えて

    1

    @TransactionalここでOKです。

    public class ApplicationServices { 
        @Transactional(propagation=Propagation.REQUIRES_NEW) 
        public void setUpdating(boolean b) { 
         // update DB here 
        } 
    } 
    

    例外の場合には、それはまだ限り、あなたはsetUpdatingへの呼び出しでを持っているようにDBを更新します:唯一のことは、それが個別にコミットしますように、あなたはREQUIRES_NEWapplicationServices.setUpdatingの伝播を設定する必要がありますfinallyブロック。

    +0

    ありがとう、この注釈は、メイントランザクションを一時的に停止する新しいトランザクションを作成します。したがって、 '@ Transactional'でアノテーションされたメソッドが同じアノテーションを持つ他のメソッドを呼び出す場合、データベースへの値はメインアノテーションの注釈だけに書き込まれますか? – luca

    +0

    'setUpdating'メソッドは、呼び出し元メソッドのトランザクションに依存しない新しいTXを使います。操作が成功すると、コミットし、他のTXにデータが表示されます。 –

    +0

    完璧です。質問の第2部分については、どう思いましたか? – luca

    1

    ここには複数の質問があり、その中には把握が難しいものがあります。ここには少し入力があります。これがあるとき:

    @Transactional(rollbackFor=FileSystemException.class) 
    private void changeDisplacement(int idApplication, int idDisplacement){ 
        applicationServices.setUpdating(true); 
    

    このフラグは、@Transactionalが終了したときにのみデータベースにヒットします。変更は、@Transactionlメソッドの終了まで、休止状態で保持されます。

    あなたはchangeDisplacementを実行している間に他の誰かが来て、そのフラグを読んでいます - あなたはまだDBに書き込んでいないので、それは偽を見るでしょう。あなたはREAD_UNCOMMITTED経由でそれを得ることができますが、これを許可するのはあなたのアプリケーションです。

    REQUIRES_NEWというメソッドを使用し、そのフラグをtrueに設定し、そのフラグを元に戻す更新があった場合は、そのフラグをtrueに設定できます。

    一般に、DBとファイルシステムの両方を更新することは容易ではありません(同期を維持する)。私がこれまでにやった方法(より良いオプションかもしれない)は、登録イベント(正しいDBが作成された後)で、ファイルシステムに書き込むことです。

    +0

    アドバイスありがとうございます。はい、setUpdatingを手動で元に戻す必要があります。データベース設計時の要件が異なるため、データベースとファイルシステムの同期化を短時間で行うことは非常に困難です。 – luca

    関連する問題