2012-05-07 13 views
2

私はいくつかの処理を行い、ORMLiteトランザクションを使用してデータベースに書き込むモジュールをAndroidで設計しています。この実行可能で、その後ThreadPoolExecutorに提出されて実行されますORMLiteをバックグラウンドスレッドで安全に書き込む

public class BackgroundOperation implements Runnable { 
     @Override 
    public void run() { 
     //Do some stuff 

     //Write to the database in a transaction 
     try { 

      ORMHelper h = ORMHelper.getDefaultOrmHelper(); 
      final MyModel modelObj = h.myModelDao.queryForId(someId); 
      TransactionManager.callInTransaction(
       h.getConnectionSource(), 
       new Callable<Void>() { 
        public Void call() throws Exception { 
         modelObj.col1 = 10; 
         modelObj.col2 = "hello"; 
         h.myModel2Dao.update(modelObj); 
         h.myModel2Dao.create(new MyModel2("a", "b")); 
         return null; 
        } 
       } 
      ); 
     } 
     catch (Exception e) { 
      return null; 
     } 
    } 
} 

:特に、私のバックグラウンドのコードは次のようになります。必要に応じてバックグラウンドスレッドをキャンセルできるようにしたいのですが、操作がキャンセルされた場合、トランザクションは単に失敗して何もしないことを確認しようとしています。たとえば、私がこれを行う場合:

Future f = myThreadPoolExecutor.submit(new BackgroundOperation()); 

//Some time later 
f.cancel(true); 

ORMLiteでのトランザクションの処理はすべて、または何も行われません。つまり、クリーンアップが不要で、modelObjにcol1とcol2の両方が設定されているか、どちらも設定されていませんか?このようにタスクがキャンセルされたときに、RunnableでInterruptedExceptionをキャッチしてケースを処理するには、何か特別な処理を行う必要がありますか?あるいは単に終了できますか?

答えて

2

あなたがf.cancel(true)を呼び出すと、しても、そのすべてがInterruptedExceptionをスローするように、wait()の原因となるThreadを中断sleep()、およびいくつかの他の方法です。 ではないデータベーストランザクションをキャンセル中です。

したい場合は、あなたがあなたのIO操作の途中で中断されたビットを確認することができます。

:スレッドはここを参照してください中断されたときに何が起こるかについての詳細は

h.myModel2Dao.update(modelObj); 
if (Thread.currentThread().isInterrupted()) { 
    throw new RuntimeException("Thread was interrupted"); 
} 
h.myModel2Dao.create(new MyModel2("a", "b")); 

What does java.lang.Thread.interrupt() do?


取引は、AR複数のオブジェクトを1つのユニットとして更新する場合や、複数のテーブルに書き込む場合に使用します。トランザクション内にAccountOrderを更新する例があるdocumentation about transactionsを参照してください。

また、同じ行の複数のフィールドを更新する場合は、トランザクションを使用する必要はありません。更新ステートメントは単一のユニットとみなされ、データベースは行がアトミックに更新されるようにする必要があります。 異なる行を同じテーブルまたは別のテーブルに複数更新する場合のみ、トランザクションが必要です。

+0

おかげでグレー...私の例は少し不注意だった/急いだが、焦点はどのようにRunnableをキャンセルする(プロセスでdb書き込みを尊重するか)です。私は、正確さのために2つの別々のテーブル編集でサンプルを更新しました。あなたが言及したところから、f.cancel()はRunnableオペレーションの確実なキャンセルとして行く方法ではないかもしれません。それが取り消され、diff時にチェックされ、通常のexecパスを終了するのに使用されるかどうかを示す、同期状態varを持つCancelableRunnableサブクラスを作成する方がいいかと思います。 – Faisal

+0

私は基本的に目的のcの[nsoperationキャンセル]機能と同等のものを得ようとしています...もしRunnable中に戦略的なタイミングで取り消しステータスをチェックして終了することができればそれは問題ありません。 – Faisal

+0

'interrupt()' @Faisalを除いて実行中にJavaスレッドを停止する方法はありません。私は私の答えを更新しました。 – Gray

0

ORMLiteは、カバーの下でsqliteトランザクションを利用します。これは、トランザクションをユニット全体としてコミットできるだけの二相コミットの可能性が最も高いです。

つまり、col1とcol2は1つのアトミック単位としてのみ変更されます。また、中断された場合はコミットが失敗し、col1とcol2への変更がロールバックされます。

+0

これはいくつかの点で間違っています。私の答えを見てください。これは二重ロックトランザクションではなく、コミットまたはロールバックできる単なるトランザクションです。同じ行の複数の列を更新するトランザクションは必要ありません。割り込みはトランザクション呼び出しに何もしません。 'sleep()'や 'wait()'だけを中断します。 – Gray

+0

私が言っていたことは、多くの異なるデータベースシステムにわたって、データベースが原子的な振る舞いを保証する1つの方法である「二相コミット」(http://en.wikipedia.org/wiki/Two-phase_commit_protocol)でした。この場合、トランザクションが必ずしも必要ではなく、isInterupted()を特に呼び出さずにrun()メソッドを中断する方法が実際にないことに私は同意します。 –

関連する問題