Hibernateの公式ドキュメントの第4章の翻訳を紹介します。記事の翻訳は、バージョンHibernate 4.2.19.Finalに関連しています次の章 -Hibernate開発者向けドキュメント-第V章ロック内容4.1。 バッチ挿入4.2。 バッチ更新4.3。 ステートレスセッション4.4。 DMLのHibernateクエリ言語4.4.1。 更新および削除のHQL4.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 ) {
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 ) {
4.3。 ステートレスセッション
StatelessSessionは、Hibernateが提供するチーム指向のAPIです。 これを使用して、デタッチされたオブジェクトの形式でデータベースとの間でデータをストリーミングします。
StatelessSessionには永続コンテキストが関連付けられておらず、ほとんどの高レベルのセマンティクスを提供しません。
StatelessSessionによって提供されない機能:- 一次キャッシュ
- 一次キャッシュまたは要求キャッシュとの相互作用
- トランザクション後書きまたは自動修正チェック( ダーティチェック )
StatelessSessionの制限:- StatelessSessionによって実行される操作は、関連するエンティティにカスケードされません
- コレクションは無視されます
- StatelessSessionを介した操作は、Hibernateイベントモデルとそのインターセプターをバイパスします。
- 一次キャッシュがないため、StatelessSessionsは複数のデータエイリアスの影響 ( データエイリアシング効果 )に対して脆弱です。
- StatelessSessionは、基礎となるJDBCにより近い低レベルの抽象化です。
例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";
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";
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_listで
idプロパティが指定されていない場合、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();