Hibernate開発者ドキュメント-章IV。 バッチ処理

Hibernateの公式ドキュメントの第4章の翻訳を紹介します。

記事の翻訳は、バージョンHibernate 4.2.19.Finalに関連しています

次の章 -Hibernate開発者向けドキュメント-第V章ロック

内容
4.1。 バッチ挿入
4.2。 バッチ更新
4.3。 ステートレスセッション
4.4。 DMLのHibernateクエリ言語
4.4.1。 更新および削除のHQL
4.4.2。 INSERTのHQL構文

次の例は、アンチバッチ挿入パターンを示しています。

例4.1 休止状態を使用して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はセッションレベルのキャッシュに新しく作成されたすべてのCustomerインスタンスをキャッシュするためです。 この問題を回避する方法はいくつかあります。
バッチ処理の使用を開始する前に、JDBCでバッチ処理を使用可能にしてください。 バッチ処理を有効にするには、 hibernate.jdbc.batch_sizeプロパティに10〜50の値を入力します。

重要です
識別子ジェネレーターを使用すると、HibernateはJDBCレベルのバッチ挿入を透過的にオフにします

このアプローチが受け入れられない場合、 hibernate.cache.use_second_level_cacheプロパティをfalseに設定することにより、2次キャッシュを無効にできます。

4.1。 バッチ挿入


新しいオブジェクトを永続化する場合は、 flush()およびclear()セッションメソッドを使用して、一次キャッシュのサイズを制御します。

例4.2 フラッシングおよびフラッシングセッション

 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(); 

4.2。 バッチ更新


データを取得および変更するときは、定期的にflush()およびclear()を使用してください。 さらに、 scroll()メソッドを使用して、多数の行を返すクエリでデータベースカーソルを使用することを利用します。

例4.3 スクロールを使用する()

 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() 

4.3。 ステートレスセッション


StatelessSessionは、Hibernateが提供するチーム指向のAPIです。 これを使用して、デタッチされたオブジェクトの形式でデータベースとの間でデータをストリーミングします。 StatelessSessionには永続コンテキストが関連付けられておらず、ほとんどの高レベルのセマンティクスを提供しません。

StatelessSessionによって提供されない機能:

StatelessSessionの制限:

例4.4 StatelessSessionの使用

 StatelessSession session = sessionFactory.openStatelessSession(); Transaction tx = session.beginTransaction(); ScrollableResults customers = session.getNamedQuery("GetCustomers") .scroll(ScrollMode.FORWARD_ONLY); while ( customers.next() ) { Customer customer = (Customer) customers.get(0); customer.updateStuff(...); session.update(customer); } tx.commit(); session.close(); 

リクエストによって返された顧客オブジェクトはすぐに切断されます。 永続コンテキストには関連付けられません。

StatelessSessionインターフェースで定義されたinsert()update() 、およびdelete()操作は、テーブルの行を直接操作します。 これらは、Sessionインターフェースで定義されたsave()saveOrUpdate() 、およびdelete()メソッドとは異なるセマンティクスを持っているため、対応するSQL操作の即時実行につながります。

4.4。 DMLのHibernateクエリ言語


DML、またはデータマークアップ言語は 、INSERT、UPDATE、DELETEなどのSQLステートメントを指します。 Hibernateは、SQLに似たDML操作をHQL( Hibernate Query Language )の形式でバッチ実行するためのメソッドを提供します。

4.4.1 UPDATEおよびDELETEのHQL



例4.5 HQLを使用したUPDATEおよびDELETE式の疑似構文

 ( UPDATE | DELETE ) FROM? EntityName (WHERE where_conditions)? 

接尾辞 オプションのパラメータを意味します。 FROMとWHEREは両方ともオプションです。
FROMは、エイリアスを持つことができる1つのエンティティのみを指すことができます。 エンティティ名にエイリアスがある場合、プロパティ参照はそのエイリアスで修飾する必要があります。 エンティティ名にエイリアスがない場合、リンクは(限定)に限定されるべきではありません。

グループHQLクエリでは、暗黙的または明示的なJoin'yは禁止されています。 WHERE句でサブクエリを使用でき、サブクエリ自体に結合を含めることができます。

例4.6。 Query.executeUpdate()メソッドを使用してHQL UPDATEを実行します

 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 = session.createQuery( hqlUpdate ) .setString( "newName", newName ) .setString( "oldName", oldName ) .executeUpdate(); tx.commit(); session.close(); 

EJB3仕様によると、HQL UPDATE式は、デフォルトでは、変更されたエンティティのバージョンまたはタイムスタンプ値に影響しません。 バージョン付き更新を使用して、UPDATEの後にVERSIONEDキーワードを追加することにより、Hibernateでバージョンまたはタイムスタンプを強制的にリセットできます。

例4.7。 タイムスタンプバージョンの更新

 Session session = sessionFactory.openSession(); Transaction tx = session.beginTransaction(); String hqlVersionedUpdate = "update versioned Customer set name = :newName where name = :oldName"; int updatedEntities = session.createQuery( hqlUpdate ) .setString( "newName", newName ) .setString( "oldName", oldName ) .executeUpdate(); tx.commit(); session.close(); 

重要です
VERSIONED式を使用する場合、 org.hibernate.usertype.UserVersionTypeクラスを使用するカスタムバージョンタイプは使用できません

例4.8 HQL DELETE

 Session session = sessionFactory.openSession(); Transaction tx = session.beginTransaction(); String hqlDelete = "delete Customer c where c.name = :oldName"; // or String hqlDelete = "delete Customer where name = :oldName"; int deletedEntities = session.createQuery( hqlDelete ) .setString( "oldName", oldName ) .executeUpdate(); tx.commit(); session.close(); 

Query.executeUpdate()メソッドは、操作の影響を受けるエンティティの数を示すint値を返します。 この数は、データベースで更新された行の数と相関する必要はありません。 HQLのグループ操作は、たとえば、結合されたサブクラス(結合されたサブクラス)の場合など、いくつかのSQL式で構成できます。 サブクラスの結合の例では、サブクラスの1つに対するDELETEにより、実際には、結合の下または継承階層の下位のテーブルで削除が行われる可能性があります。

4.4.2 INSERTのHQL構文


例4.9 INSERT式の疑似構文

 INSERT INTO EntityName properties_list select_statement 

INSERT INTO ... SELECT ...形式のみがサポートされており、挿入する明示的な値を指定することはできません。

properties_listは、INSERT SQLステートメントで列を指定するための類似物です。 マップされた継承に関与するエンティティの場合、サブクラスまたは親クラスからではなく、クラス自体で直接指定されたプロパティを指定できます。 言い換えると、INSERTステートメントは本質的にポリモーフィックではありません。

select_statementは任意の有効なHQL選択クエリにできますが、返される型はINSERTで予期される型と一致する必要があります。 Hibernateは、DBMSがチェックするのを待たずに、コンパイル時に戻り値の型をチェックします。 問題はHibernateタイプから発生する可能性があります。Hibernateタイプは同等である可能性が高く、同等ではありません。 この1つの例は、データベースがそれらを区別しない場合、または型変換自体が可能である場合でも、org.hibernate.type.DateTypeとして定義されたプロパティとorg.hibernate.type.TimestampTypeとして定義されたプロパティの不一致です。

properties_listidプロパティが指定されていない場合、Hibernateは自動的に値を生成します。 自動生成は、IDジェネレーターを使用する場合にのみ使用できます。 そうでない場合、Hibernateは解析中に例外をスローします。 データベースで利用可能なジェネレーターは、 org.hibernate.id.SequenceGeneratorとそのサブクラス、およびorg.hibernate.id.PostInsertIdentifierGeneratorを実装するオブジェクトです。 最も注目すべき例外はorg.hibernate.id.TableHiLoGeneratorで 、値を取得する方法を提供しません。
バージョンまたはタイムスタンプとして投影されるプロパティの場合、挿入式には2つのオプションがあります。 properties_listでプロパティを指定できます。その場合、値は付随するselect-expressionから取得されます。または、 properties_listから削除されます 。この場合、 org.hibernate.type.VersionTypeで定義された初期(シード)値が使用されます。

例4.10。 HQL INSERT式

 Session session = sessionFactory.openSession(); Transaction tx = session.beginTransaction(); String hqlInsert = "insert into DelinquentAccount (id, name) select c.id, c.name from Customer c where ..."; int createdEntities = session.createQuery( hqlInsert ) .executeUpdate(); tx.commit(); session.close(); 

Source: https://habr.com/ru/post/J269029/


All Articles