私はそれを理解するために一晩中過ごしました、そして私はこの時点で必死です。Grails2.1.0プロジェクトにサービスクラスがあります。Webサービスに対してクエリを実行します-クエリはスレッド化されます。スレッドがデータを取得すると、synchronized
メソッドWriteToDB
を呼び出します。メソッドは名前(String field
)を取り、。を介してドメインをチェックしますfindByName
。レコードが存在する場合は、他に何もせずに新しいレコードを作成します。
今私はチェックしました、そしてメソッドは確かに一度に呼び出されるのに1つのスレッドだけを許可します、これはログサンプルです:
エラー2013-01-0221:29:47,408[スレッド-21]エラー-WriteToDBSTART
エラー2013-01-0221:29:47,474[スレッド-21]エラー-WriteToDBが終了しました
エラー2013-01-0221:29:47,475[スレッド-20]エラー-WriteToDBSTART
エラー2013-01-0221:29:47,571[スレッド-20]エラー-WriteToDBが終了しました
エラー2013-01-0221:29:47,581[スレッド-49]エラー-WriteToDBSTART
エラー2013-01-0221:29:47,866[スレッド-49]エラー-WriteToDBが終了しました
エラー2013-01-0221:29:47,867[スレッド-45]エラー-WriteToDBSTART
エラー2013-01-0221:29:48,202[スレッド-45]エラー-WriteToDBが終了しました
エラー2013-01-0221:29:48,203[スレッド-48]エラー-WriteToDBSTART
エラー2013-01-0221:29:48,320[スレッド-48]エラー-WriteToDBが終了しました
ただし、レコードが重複しています!!! 新しいレコードを保存するたびにflush:true
、それを実行します。なぜそれが起こり続けるのか分かりませんか?手動でテストしました。テストの前に1つの既知のレコードをDBに追加しましたが、複製されることはありませんでしたが、保存されている新しいレコードは最大6回複製されます。
助けてください。何かにインデックスを付ける必要がありますか?または、特別な方法で何かをフラッシュしますか?なぜそれが起こっているのですか?
[2013年2月1日更新]:
レコードを保存するために使用しているコードは次のとおりです。
if(!f) { // Check if record doesn't exist then save, else nothing
f = new Feature(name: featureName)
if( !f.save(flush: true) ) {
f.errors.each {
log.error it
}
}
}
また、エラーサンプル:
エラー2013-01-0222:25:58,868[スレッド-20]エラーutil.JDBCExceptionReporter-キー「名前」のエントリ「自動送信」が重複しています
エラー2013-01-0222:25:58,873 [スレッド-20]エラーhibernate.AssertionFailure-アサーションエラーが発生しました(これはHibernateのバグを示している可能性がありますが、セッションの安全でない使用が原因である可能性が高いです)メッセージ:null id Project2.Featureエントリ内(例外が発生した後にセッションをフラッシュしないでください)
私はこのように解釈することができます(コードの「保存」部分の前にFindByNameを取得しました):レコードを検索し、それが存在しないため、作成しています。重複エントリについて文句を言い、変数「f」に対してnullを取得しています後でリレーションとして別のテーブルに挿入します。
私はtrycatchブロックでこのコードを修正しようとするかもしれないと思います...アイデア?