Hibernate 4.1.0が提供するSpring 3.1/JPA 2の使用。Hibernate/JPA @Versionと@GeneratedがStaleObjectStateExceptionの原因となる
基本的な監査機能(タイムスタンプ、バージョン番号の更新など)を提供するすべてのエンティティの基本クラスを用意しています。他のアプリケーションがデータベースにアクセスするため、これらはトリガーで設定する必要があります。そしてStaleObjectStateException
で結果 -
public abstract class AbstractBaseModel implements Serializable {
@Version
@Generated(GenerationTime.ALWAYS)
@Column(name = "VERSION", insertable = false, updatable = false)
protected Long version;
@Generated(GenerationTime.ALWAYS)
@Column(name = "UPDATE_TIMESTAMP", insertable = false, updatable = false)
protected Date updateDate;
...
}
org.hibernate.engine.internal.increment(...)
メソッドは常にトランザクションをコミットするときに呼び出されます。
私のマッピングは次のようになります。
バージョンの列にGenerationTime.NEVER
を設定しても不思議ではありませんが、hibernateはまだバージョンをインクリメントしますが、正しく維持されます。問題は、データベースのバージョンが更新されない場合(たとえテーブルに変更がない場合でも)、マージから返されたバージョンがデータベース値より1高くなり、後続のセーブで明らかに問題が発生することです。
GenerationTime.ALWAYS
は、バージョンをインクリメントしてデータベースに依存せず、挿入/更新してから更新された値を選択することを決して避けたいと考えています。
どこの人が私の理解と実装に間違っているのか教えていただけますか?
ああ、あなたは私の問題を解決したが、悲しんではいけなかった。これは '@ Version'と' @ Generated'と同じ動作をします。フラッシュが発生する前に常にバージョンをインクリメントし、オプティミスティックロック例外を発生させます。私が望むのは、いつも '@ Generated'とマークされたフィールドを増やそうとしないことです。これはOracle固有の問題ですが、私は完全に困惑しています。 – Ben
これは実際には本当に不思議です。このコードは、数ヶ月間、本番環境で問題なく実行されています。私はあなたを助けることができなかったことに非常に残念です、私は本当にあなたの問題を解決するだろうと思った... – LeChe