1

次のコードと休止状態の構成に相当します (基本的に、StreamRef はテープに属し、そのテープで一意である必要があります)。

<class name="StreamRef" table="StreamRefToTape">
 <composite-id> <key-property name="UUID"/> 
   <key-many-to-one class="Tape" name="tape">
     <column name="Tape_TapeId" not-null="true"/>
   </key-many-to-one>
 </composite-id>
 ...</class>

 <class name="Tape" table="Tape">
 <id column="TapeId" name="tapeId"/></class>

私はこれらの StreamRef を何百万も持っており、それらをすべて同じトランザクション内に保存したいと考えていますが、このトランザクション中に RAM も節約したいと考えています。

そこで、次のコードを試してみました.CacheModeをオフにすると、内部でオブジェクトを追跡しないため、RAMを大幅に節約できると思います(これはある程度役立つようです)。しかし、この仮説を検証すると、次のようになります。

 session = sessionFactory.openSession();
 session.setCacheMode(CacheMode.IGNORE);   // disable the first level cache
 session.beginTransaction();
 Tape t = new Tape();
 StreamRef s1 = new StreamRef("same uuid");
 StreamRef s2 = new StreamRef("same uuid"); // force a primary key collision
 session.saveOrUpdate(t);
 for(StreamRef s : t.getStreams()) {
     session.save(s);
 }
 session.commit();

CacheMode をオフにしたため、これが発生しないと予想していました (ただし、NonUniqueObjectException https://gist.github.com/4542569が発生します)。1) 休止状態の内部キャッシュが無効にできないことを確認してください。2) この例外は CacheMode とは関係ありませんか? ここで必要なことを達成する方法はありますか (トランザクション内で大量の休止状態の RAM を使い切らないようにするには?)

多少関連:https://stackoverflow.com/a/3543740/32453

(副次的な質問として... setCacheMode が beginTransaction と関連して呼び出される順序は重要ですか? 私はそうではないと思いますか?)

どうもありがとう。

4

2 に答える 2

1

例外は理にかなっています。Hibernate にプレイすることを伝えたルールに違反しています。コーディングしたことを本当に実行したい場合は、StatelessSession API または createSQLQuery API を使用する必要があります。現状では、Session.setCacheMode は、セッション キャッシュではなく、第 2 レベルのキャッシュと対話するためのものです。

メモリ使用量に関しては、Hibernate がActionQueueをパージできるように、レコードのバッチを段階的にディスクにフラッシュする必要があります。

ユーザー ガイドのバッチ更新に関するセクションの例を次に示します。

Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();

for ( int i=0; i<100000; i++ ) {
    Customer customer = new Customer(.....);
    session.save(customer);
    if ( i % 20 == 0 ) { //20, same as the JDBC batch size
        //flush a batch of inserts and release memory:
        session.flush();
        session.clear();
    }
}

tx.commit();
session.close();

同じ章でステートレス セッションについても読むことができます。

于 2013-01-15T03:25:16.163 に答える
1

Hibernate はすべてのセッション オブジェクトを一度に保存します...キャッシュは他のセッションのオブジェクトを保存します...そのため、単一のセッションで自分のオブジェクトを無効にすることはできません... merge() を使用しようとすることはできません... .

于 2013-01-15T03:32:44.590 に答える