[解決済み] 行が他のトランザクションによって更新または削除された(または未保存の値のマッピングが不正確であった)
質問
私はウェブサーバー上で実行されるJavaプロジェクトを持っています。いつもこの例外に遭遇します。
私はいくつかのドキュメントを読み、悲観的なロック(または楽観的な、しかし私は悲観的な方が良いと読んだ)がこの例外を防ぐのに最適な方法であることがわかりました。
しかし、その使い方を説明する明確な例が見つかりませんでした。
私のやり方はこうです。
@Transactional
public void test(Email email, String subject) {
getEmailById(String id);
email.setSubject(subject);
updateEmail(email);
}
の間に
-
Email
はHibernateのクラスです(データベースのテーブルになります)。 -
getEmailById(String id)
を返す関数です。email
(というアノテーションがあります(このメソッドには@Transactional
) -
updateEmail(email)
: は、メールを更新するメソッドです。
注意
保存、更新&などにHibernateを使っています(例.
session.getcurrentSession.save(email)
)
例外が発生した。
ERROR 2011-12-21 15:29:24,910 Could not synchronize database state with session [myScheduler-1]
org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [email#21]
at org.hibernate.persister.entity.AbstractEntityPersister.check(AbstractEntityPersister.java:1792)
at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:2435)
at org.hibernate.persister.entity.AbstractEntityPersister.updateOrInsert(AbstractEntityPersister.java:2335)
at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:2635)
at org.hibernate.action.EntityUpdateAction.execute(EntityUpdateAction.java:115)
at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:279)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:263)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:168)
at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:321)
at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:50)
at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1027)
at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:365)
at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:137)
at org.springframework.orm.hibernate3.HibernateTransactionManager.doCommit(HibernateTransactionManager.java:656)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:754)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:723)
at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:393)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:120)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
at $Proxy130.generateEmail(Unknown Source)
at com.admtel.appserver.tasks.EmailSender.run(EmailNotificationSender.java:33)
at com.admtel.appserver.tasks.EmailSender$$FastClassByCGLIB$$ea0d4fc2.invoke(<generated>)
at net.sf.cglib.proxy.MethodProxy.invoke(MethodProxy.java:149)
at org.springframework.aop.framework.Cglib2AopProxy$CglibMethodInvocation.invokeJoinpoint(Cglib2AopProxy.java:688)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150)
at org.springframework.aop.aspectj.AspectJAfterThrowingAdvice.invoke(AspectJAfterThrowingAdvice.java:55)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:161)
at org.springframework.aop.framework.adapter.AfterReturningAdviceInterceptor.invoke(AfterReturningAdviceInterceptor.java:50)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:161)
at org.springframework.aop.framework.adapter.MethodBeforeAdviceInterceptor.invoke(MethodBeforeAdviceInterceptor.java:50)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:161)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:89)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.framework.Cglib2AopProxy$DynamicAdvisedInterceptor.intercept(Cglib2AopProxy.java:621)
at com.admtel.appserver.tasks.EmailNotificationSender$$EnhancerByCGLIB$$33eb7303.run(<generated>)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.springframework.util.MethodInvoker.invoke(MethodInvoker.java:273)
at org.springframework.scheduling.support.MethodInvokingRunnable.run(MethodInvokingRunnable.java:65)
at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:51)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:441)
at java.util.concurrent.FutureTask$Sync.innerRunAndReset(FutureTask.java:317)
at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:150)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$101(ScheduledThreadPoolExecutor.java:98)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.runPeriodic(ScheduledThreadPoolExecutor.java:180)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:204)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:680)
ERROR 2011-12-21 15:29:24,915 [ exception thrown < EmailNotificationSender.run() > exception message Object of class [Email] with identifier [211]: optimistic locking failed; nested exception is org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [Email#21] with params ] [myScheduler-1]
org.springframework.orm.hibernate3.HibernateOptimisticLockingFailureException: Object of class [Email] with identifier [21]: optimistic locking failed; nested exception is
解決方法は?
悲観的なロックは一般的に推奨されませんし、データベース側のパフォーマンスという点でも非常にコストがかかります。あなたが言及した問題(コード部分)は、以下のようにいくつかの点が明確ではありません。
- コードが複数のスレッドから同時にアクセスされている場合。
-
をどのように作成していますか?
session
オブジェクトを作成しましたか(Springを使用しているかどうかは不明)?
ハイバーネート セッションオブジェクトはスレッドセーフではありません . そのため、同じセッションにアクセスするスレッドが複数あり、同じデータベース・エンティティを更新しようとした場合、あなたのコードはこのようなエラー状況に陥る可能性があるのです。
つまり、複数のスレッドが同じエンティティを更新しようとし、1つのスレッドが成功し、次のスレッドがデータをコミットしようとしたときに、そのデータがすでに変更されていることがわかり、以下のようにスローされます。
StaleObjectStateException
.
EDIT :
HibernateでPessimistic Lockingを使用する方法があります。チェックアウト このリンク . しかし、この仕組みには何か問題があるようです。私はhibernateのバグを投稿しているところに出くわしました( HHH-5275 )が、しかし。バグに記載されているシナリオは以下の通りです。
2つのスレッドが同じデータベースレコードを読み込んでいる場合、そのうちの1つのスレッド は悲観的ロックを使用し、それによってもう一方のスレッドをブロックする必要があります。しかし 両方のスレッドがデータベースレコードを読み取ることができ、テストは失敗します。
これは、あなたが直面していることに非常に近いです。これがうまくいかない場合、私が思いつく唯一の方法は、次のものを使用することです。
ネイティブSQLクエリ
を実現できるところ。
Postgres における悲観的なロック
データベースで
SELECT FOR UPDATE
クエリを実行します。
関連
-
[解決済み】エラー「No enclosing instance of type Foo is accessible」の原因と修正方法について教えてください。
-
[解決済み】Javaクラスの "型に解決できない"
-
[解決済み] hibernate のプロパティが見つかりません。
-
[解決済み】Javaの部分文字列:「文字列のインデックスが範囲外」。
-
[解決済み】なぜjava.io.Fileにはcloseメソッドがないのでしょうか?
-
[解決済み】「java -cp」と「java -jar」の違い?
-
[解決済み】JLabelのテキストを中央に配置するには?
-
[解決済み】予期しない型エラー
-
[解決済み】koch snowflake java recursion
-
[解決済み】CreateProcess error=2, The system cannot find file specified.
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】javaで指定されたファイルが見つからない
-
[解決済み] hibernate のプロパティが見つかりません。
-
[解決済み】「error: '.class' expected」の意味と修正方法について
-
[解決済み】Javaでユーザー入力を待機させる方法
-
[解決済み】Eclipseで「JUnitテストが見つかりませんでした。
-
[解決済み] StringBuilderをクリアまたは空にするにはどうすればよいですか?重複] [重複] [重複] [重複] [重複] [重複
-
[解決済み] JavaでSSLピアが正しくシャットダウンされない
-
[解決済み】Java: GZIPInputStreamの作成に失敗しました。GZIP形式ではありません
-
[解決済み】Eclipseで「パッケージエクスプローラー」ビューが見つからない
-
[解決済み】 executeQuery()でデータ操作文が発行できない。)