session.saveOrUpdate()
が呼び出されたときにHibernateがデータベース内の値をINSERTするかUPDATEするかをどのように知るかを知っていますか?
これまでのところ、キャッシュ内の情報に依存するものではなく、データベース内のエンティティの存在は主キーによって決定されると判断しました。
.saveOrUpdate()
を使用すると、Hibernateはオブジェクトが一時的(識別子プロパティを持たない)かどうかを確認し、そうであれば識別子を生成してセッションに割り当てることで永続化します。オブジェクトに既に識別子がある場合、.update()
を実行します。
ドキュメント から:
saveOrUpdate()は次のことを行います。
おそらく、Hibernateの聖書を引用すると役立つでしょう( Java Persistence with Hibernate、2nd ed。 、528ページ):
より経験豊富なHibernateユーザーは
saveOrUpdate()
を排他的に使用します。特に混合状態のオブジェクトのより複雑なネットワークでは、Hibernateが何が新しく何が古いかを決定するのがはるかに簡単です。排他的なsaveOrUpdate()
の唯一の(本当に深刻ではない)欠点は、データベースでSELECT
を起動しないとインスタンスが古いか新しいかを推測できないことがあることです。たとえば、クラスは、バージョンまたはタイムスタンププロパティのない自然な複合キーでマップされます。Hibernateはどのインスタンスが古いインスタンスと新しいインスタンスをどのように検出しますか?さまざまなオプションが利用可能です。 Hibernateは、次の場合にインスタンスが保存されていない一時インスタンスであると想定します。
- 識別子プロパティは
null
です。- バージョンまたはタイムスタンププロパティ(存在する場合)は
null
です。- Hibernateによって内部的に作成された同じ永続クラスの新しいインスタンスは、指定されたインスタンスと同じデータベース識別子の値を持ちます。
- クラスのマッピングドキュメントで_
unsaved-value
_を指定すると、識別子プロパティの値が一致します。 _unsaved-value
_属性は、バージョンおよびタイムスタンプのマッピング要素にも使用できます。- 同じ識別子値を持つエンティティデータは、2次キャッシュにありません。
- 実装または_
org.hibernate.Interceptor
_を指定し、コード内のインスタンスをチェックした後、Interceptor.isUnsaved()
から_Boolean.TRUE
_を返します。
前述のように、 here 、saveOrUpdate
は、新しい識別子を生成して一時的なインスタンスを保存するか、現在の識別子に関連付けられた分離されたインスタンスを更新/再接続します。より具体的には:
save()
it<version>
_または_<timestamp>
_によってバージョン管理され、バージョンプロパティ値がsave()
itupdate()
オブジェクト誰かが理論的に本当に理解していないなら、コードがあります
MyModel sent = myDao.myDaoImpl(id);
if(sent == null){
sent = **new MyModel();** // new Object
sent.setXX(id);
sent.setYY("Yes");
sent.setDate(new Date());
myDao.saveOrUpdate(sent); // Insert will be called
} else if(! "Yes".equalsIgnoreCase(sent.getFlag())) {
sent.setXX("Yes");
sent.setDate(new Date());
myDao.saveOrUpdate(sent); // Update will be called
}
これは、主キーの値に基づいて行われます。主キーが未定義の場合、数値の代理キーの値はデフォルトで0になり、save
が実行されます。主キーが入力されると、update
を呼び出します。