この種の処理のドキュメントを見るのに適切な場所は、第13章全体です。バッチ処理。
ここで、現在のアプローチにはいくつかの明らかな間違いがあります。
- 更新ごとにトランザクションを開始/コミットしないでください。
JDBCバッチ処理を有効にして、適切な数(10〜50)に設定する必要があります。
hibernate.jdbc.batch_size 20
flush()
その後、定期的にセッションを実行する必要がありclear()
ます(nがパラメータに等しいnレコードごと) 。そうしないと、セッションは成長し続け、ある時点でhibernate.jdbc.batch_size
爆発する可能性があります( )。OutOfMemoryException
以下、セクション13.2に示されている例。これを示すバッチ更新:
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
ScrollableResults customers = session.getNamedQuery("GetCustomers")
.setCacheMode(CacheMode.IGNORE)
.scroll(ScrollMode.FORWARD_ONLY);
int count=0;
while ( customers.next() ) {
Customer customer = (Customer) customers.get(0);
customer.updateStuff(...);
if ( ++count % 20 == 0 ) {
//flush a batch of updates and release memory:
session.flush();
session.clear();
}
}
tx.commit();
session.close();
StatelessSessionの使用を検討することもできます。
もう1つのオプションは、DMLスタイルの操作(HQLで!)を使用することですUPDATE FROM? EntityName (WHERE where_conditions)?
。これはHQLUPDATEの例です。
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
String hqlUpdate = "update Customer c set c.name = :newName where c.name = :oldName";
// or String hqlUpdate = "update Customer set name = :newName where name = :oldName";
int updatedEntities = s.createQuery( hqlUpdate )
.setString( "newName", newName )
.setString( "oldName", oldName )
.executeUpdate();
tx.commit();
session.close();
繰り返しになりますが、詳細(特にキーワードを使用してversion
またはtimestamp
プロパティ値を処理する方法)については、ドキュメントを参照してください。VERSIONED