MySQL で Grails 1.3.7 を使用しています。私のアプリケーション サーバーは、ユーザーが実行したクエリの検索結果を記録します。スキーマ (簡略化) は以下で構成されます。
class Query {
String query
String user
}
class Document {
String externalId
String title
}
class Posting {
Query query
Document document
int rank
}
ユーザーが初めてドキュメントを取得するクエリを実行するたびに、新しいインスタンスを作成します。それ以外の場合は、対応するインスタンスを作成するときに既存のインスタンスを再利用しPosting
ます。特定の に対して のインスタンスは 1 つだけ Document
存在する必要がありますexternalId
が、複数のPosting
インスタンスがそれを指すことができます。
複数のユーザーが同じドキュメントを取得するクエリを実行できますが、同時実行の問題が発生します。2 人のユーザーがほぼ同時に同じドキュメントを初めて取得した場合、 を作成しようとする 2 回目の試行はDocument
、 での一意制約違反で失敗しexternalId
ます。これはいい。悪いことPosting
に、複製に関連付けられた新しく作成されたインスタンスDocument
もロールバックされます。保存を再試行する方法を理解するのが難しいため、これは良くありません。
私が思いついた解決策は、Document
を呼び出す同期メソッドを使用してを作成しsave(flush: true)
、それが失敗した場合は、データベースからドキュメントを再度読み取ることです。次に、結果のドキュメント (保存または再読み込み) を使用して、Posting
インスタンスに入力します。このソリューションは機能しますが、ユーザーが取得した結果を処理するには遅すぎます。パラメータを削除flush: true
するとパフォーマンスは向上しますが、インスタンスが適切に作成されるDocument
とPosting
は限りません。
この種の更新を実装する正しい方法は何ですか?
明確化
私が実行しているクエリは、一度に 100 件の一致を返します。つまり、ユーザー リクエストごとに 0 Document
~ 100 個のインスタンスと 100 個のインスタンスを作成しています。Posting