第14章バッチ処理(Batch processing)


第14章バッチ処理(Batch processing)
Hibernateを使用して100,000件のレコードをデータベースに挿入するのは自然な方法かもしれません.
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
for ( int i=0; i<100000; i++ ) {
    Customer customer = new Customer(.....);
    session.save(customer);
}
tx.commit();
session.close();

このプログラムは約50,000件のレコードを実行すると失敗し、メモリオーバーフロー異常(OutOfMemoryException)が放出されます.これは、Hibernateが新しく挿入したすべてのクライアントインスタンスをsessionレベルのキャッシュ領域でキャッシュしたためです.
この章では、このような問題を回避する方法を説明します.まず、バッチ処理を実行し、理想的なパフォーマンスを達成するには、JDBCのバッチ機能を使用することが重要です.JDBCのバッチ・キャプチャ数(batch size)パラメータを適切な値(例えば、10-50の間)に設定します.
hibernate.jdbc.batch_size 20

バッチ処理を実行するときに2次キャッシュを閉じることもできます.
hibernate.cache.use_second_level_cache false

14.1.バッチ挿入(Batch inserts)
多くのオブジェクトを永続化するには、flush()を頻繁に呼び出し、clear()を後で呼び出すことで、第1レベルのキャッシュのサイズを制御する必要があります.
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 //20, JDBC      
        //flush a batch of inserts and release memory:
        //                    
        session.flush();
        session.clear();
    }
}
   
tx.commit();
session.close();

14.2.一括更新(Batch updates)
この方法は、データの取得と更新にも適用されます.また、多くのロー・データを返すクエリーを行う場合は、scroll()メソッドを使用して、サーバ側カーソルのメリットを十分に活用する必要があります.
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();

14.3.大量更新/削除(Bulk update/delete)
既に説明したように、自動および透明なオブジェクト/リレーションシップマッピング(object/relational mapping)は、管理オブジェクトのステータスに注目します.これは、オブジェクトのステータスがメモリに存在することを意味します.したがって、(SQL文UPDATEおよびDELETEを使用して)データベース内のデータを直接更新または削除しても、メモリ内のオブジェクトステータスおよびオブジェクトデータには影響しません.ただし、Hibernateは、Hibernateクエリ言語(第15章HQL:Hibernateクエリ言語)によって大量のSQLスタイルの(UPDATE)文と(DELETE)文を実行する方法を提供する.
UPDATE文とDELETE文の構文は、(UPDATE|DELETE)FROM?ClassName (WHERE WHERE_CONDITIONS)?. いくつかの説明があります.
  • FROM句(from-clause)では、FROMキーワードはオプションの
  • である.
  • FROM句(from-clause)にはクラス名が1つしかなく、別名
  • はありません.
  • 大量のHQL文では接続を使用できません(明示的または暗黙的には使用できません).ただし、WHERE句ではサブクエリを使用できます.
  • WHERE句全体がオプションです.

  • 例を挙げるとQuery.ExcuteUpdate()メソッドは、HQL UPDATE文を実行します.
    Session session = sessionFactory.openSession();
            Transaction tx = session.beginTransaction();
    
            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();

    同様にQQueryを使用するHQL DELETEを実行します.ExcuteUpdate()メソッド(JDBC PreparedStatement.executeUpdate()に詳しい人のために設定されています)
    Session session = sessionFactory.openSession();
            Transaction tx = session.beginTransaction();
    
            String hqlDelete = "delete Customer where name = :oldName";
            int deletedEntities = s.createQuery( hqlDelete )
                                .setString( "oldName", oldName )
                                .executeUpdate();
            tx.commit();
            session.close();

    Query.executeUpdate()メソッドで返される整数値は、この操作の影響を受けるレコードの数を示します.この値は、データベース内の(最後のSQL文)によって影響された「行」と一致する可能性があります.数に関係していますが、ないかもしれません.大量のHQL操作は、joined-subclassマッピング方式のクラスに対するこのような操作を例に挙げると、複数の実際のSQL文が実行される可能性があります.この戻り値は、実際に文によって影響されたレコードの数を表します.そのjoined-subclassの例では、1つのサブクラスの削除は、実際にはサブクラスがマッピングしたテーブルだけでなく、「ルート」テーブルにも影響し、継承関係のあるjoined-subclassマッピング方式のサブクラスのテーブルにも影響する可能性があります.
    なお、上記の大量のHQL操作の少数の制限は、新しいバージョンで改善される.さらに詳しくはJIRAの路線図(roadmap)を参照してください.
    原文住所:http://oss.org.cn/ossdocs/framework/hibernate/reference-v3_zh-cn/batch.html