6

Hibernate (4) と Oracle のセットアップで SQL の更新を減らす方法を考えています。

単純なケースは次のとおりです。

セッション/トランザクションを開き、session.save() で新しいエンティティ Xyz を作成し、いくつかのビジネス ロジックを処理し、Xyz にいくつかの変更を加えて session.update() を呼び出し、セッションを通常どおり閉じ、DB にコミットして休止状態にします。

コミットするとき、Hibernate は挿入に続いて更新を行いますが、実際に必要なのは単一の挿入だけですが、この例では Xyzの最新のプロパティを使用しています。

この種のことを行うためのアイデア/パターンはありますか? または、これに関する Hibernate の動作を変更する方法はありますか? または、これについてどう思いますか? それは完全なアンチパターンですか?

ある更新が別の更新を上書きするだけの場合、Hibernate は複数の更新を省略できるほどスマートであることを知っています。

この小さなスニペットは、「問題」を再現できます。

MyEntity e = new MyEntity("xxx"); 
Session session = sessionFactory.openSession(); 
session.beginTransaction();
session.save(e); e.setName("yyy"); 
session.getTransaction().commit(); 
session.close();

ちなみに、気になるトリガーはありません。

この例は非常に単純で、パフォーマンスの問題は些細なことのように思えるかもしれませんが、実際には、より複雑なオブジェクト (つまり、複数の挿入と更新) と大量のオブジェクトを扱っているため、更新を回避することは素晴らしいことです。

4

1 に答える 1

1

オブジェクトをセッションに追加する方法はありますか?それは永続的としてマークされますが、最後まで save() を呼び出さないでください (つまり、INSERT は生成されません)。

セッションがフラッシュされるか、トランザクションが閉じられるまで実行を延期する場合は、Session.persist(Object)代わりにリファクタリングを使用することを検討してください。Session.save(Object)INSERT

JBoss Hibernate Community ドキュメントのセクション 10.2 から:

EJB3 初期ドラフトで定義されたセマンティクスを使用して、save() の代わりに persist() を使用することもできます。

  • persist()一時インスタンスを永続化します。ただし、識別子の値が永続インスタンスにすぐに割り当てられることは保証されません。割り当てはフラッシュ時に発生する可能性があります。 また、トランザクション境界の外で呼び出された場合persist()、ステートメントを実行しないことも保証します。INSERTこれは、拡張されたセッション/永続コンテキストを使用した長時間の会話で役立ちます。
  • save()識別子を返すことを保証します。識別子を取得するために実行する必要がある場合INSERT(「シーケンス」ではなく「アイデンティティ」ジェネレーターなど)、INSERTトランザクションの内部または外部に関係なく、これはすぐに行われます。これは、拡張されたセッション/永続コンテキストを使用した長時間の会話では問題になります。

別の有用な参照は、このブログ記事の「すべてをまとめる」セクションの上部にあるメソッドからシナリオへのグリッドの左上のセルにあり、永続化されたことのないオブジェクトの動作について次のように説明しています。 :persist()

  1. 新しいエンティティとして永続化コンテキストに追加されたオブジェクト
  2. flush()/でデータベースに挿入された新しいエンティティcommit()
于 2013-07-04T06:05:44.477 に答える