2012-03-06 12 views
3

"JobStatus"というプレイモデルがあり、JobStateを持つ列挙型(Running/notRunning)という1つのプロパティがあります。Playモデル保存関数がデータベースに実際に書き込んでいない

クラスはモデルを拡張し、シングルトンとして実装されます。基礎となる表の唯一のレコードを取得するには、getInstance()メソッドを呼び出します。

私は毎月実行されるジョブを持っています。ジョブでは、JobStatusオブジェクトの状態をさまざまなタイミングで前後に切り替え、.save()を呼び出します。

実際には保存されていないことに気付きました。

仕事がオフに起動すると、それはコードの最初の行だが

JobStatus thisJobStatus = jobStatus.getInstance(); 
...// exit if already running 

thisJobStatus.JobState = JobState.Running; 
thisJobStatus.save() 

でジョブが実行されたときに、それは戻ってNotRunningにステータスを変更し、もう一度保存します。

MySqlデータベースを見ると、実際のレコード値は変更されません。

これは、他のノードがジョブを実行しようとすると状態をチェックし、NotRunningと見なしているため、ジョブを実行しようとするため、致命的なエラーが発生します。

実際の値がDBにコミットされないため、ジョブ状態を管理するためのわかりやすいスキームが失敗しています。

モデルで.save()を呼び出すと、すぐに再生が強制的にDBに書き込まれますか?

おかげ ジョシュ

+0

私はPlayのドキュメントごとに非トランザクションとして関数を宣言しようとしましたが、うまくいきませんでした。 –

+0

...トランザクションの場合... –

+0

ジョブの状態をトグルしてDBに書き込むことは、長時間実行されているプレイジョブ内で行われる操作であると考えているだけです。 –

答えて

3

試して、あなたとJobStatusにこれを追加し、保存した後、それを呼び出します。

public static void commit(){ 
    JobStatus.em().getTransaction().commit(); 
    JobStatus.em().getTransaction().begin(); 
    JobStatus.em().flush(); 
    JobStatus.em().clear(); 
} 
+0

これは部分的に働きました。状態は "実行中"に設定され、ジョブは実行されましたが、ジョブの最後に状態を "NotRunning"に戻すときに.save()を呼び出しました。 commit()、私の既存のJobStatusインスタンスで、私は次のエラーが発生します。 'PersistenceExceptionが発生しました:org.hibernate.PersistentObjectException:分離されたエンティティがpersist:models.JobStatus'に渡されました。私のインスタンスはもはや最初の保存後の保存に有効ではありませんか? DBから再クエリするには、getInstance()を再度呼び出す必要がありますか? –

+0

私はとてもスマートなSMRTです。私はDBからオブジェクトを再配置する必要がありました。今私はヘルパー機能を持っています。 '//ジョブ状態を管理するためのヘルパー \t private void MarkJobRunning(){ \t \t BillingJob thisJob = BillingJob.getInstance(); \t \t thisJob.state = JobState.Running; \t \t thisJob.save(); \t \t thisJob.commit(); \t} \t \tプライベートボイドMarkJobNotRunning(){ \t \t BillingJob thisJob = BillingJob.getInstance()。 \t \t thisJob.state = JobState.NotRunning; \t \t thisJob.save(); \t \t thisJob.commit(); \t} 'ありがとうございます@ emt14 !!しかしこれは一般的に良い習慣ですか?私はすべてのモデルにコミットメソッドを追加するようになりました。 –

+0

良いか悪いのか分かりません。ただし、ジョブはトランザクション内で実行されるため、ジョブが実行中のときにデータをデータベースに保存する唯一の方法です。実際には別のものがあります。あなたの最初の仕事から別の仕事を呼び出すことは可能です。 2番目のジョブは別のトランザクションを開始し、そのジョブで変更されたデータは、最初のジョブがまだ実行されている間は永続化されます。 – emt14

0

ジョブの開始時にジョブを「実行中」としてマークしたいとしますか?その場合、他に進行中のデータベースステートメントはまだありません。

thisJobStatus.save();メソッド呼び出しの後に、(ジョブが終了した後ではなく)すぐにデータベースの変更をコミットするには、次のコマンドを追加します。

JPA.em().flush(); 
JPA.em().getTransaction().commit(); 

MySQLを使っているので、また、あなたはSELECT ... FOR UPDATE句を使用してretriveval直後に行をロックしたい場合があります。 (詳しくは、MySQL Reference Manualを参照してください)もちろん、あなたのgetInstance()メソッドではそうしたくないでしょう。そうしないと、フェッチ操作ごとにレコードがロックされます。

+0

私はこれを昨日トムを試してみましたが、仕事のDB文が始まったときにいつもエラーを引き起こしました。 @ emt14の解決策が働いた。トランザクションのコミットを実際のモデル自体の中の関数に置くことによって、コミットは残りの仕事を壊すようには見えません。 –

関連する問題