この記事の研究は、主に次のように、冬眠キャッシュメカニズムに焦点を当てています。
Student.java:
パブリッククラスの学生{/*学生ID*/private int id;/*学生名*/プライベート文字列名;/*学生とクラス間の関係*/プライベートクラスクラス; //セッターとゲッターメソッドを省略}classes.java:
パブリッククラスクラス{/*クラスID*/プライベートIDStudent.hbm.xml:
<?xml version = "1.0"?> <!doctype hibernate-mapping public " - // hibernate/hibernateマッピングDTD 3.0 // en" "http://hibernate.sourceforge.net/hibernate-mapting-3.0.dtd"テーブル= "t_student"> <id name = "id"> <generator // id> <! - map normal properties-> <property name = "name"/> <! - 多額のマッピング、複数のエンドに外部キーを追加します。
classes.hbm.xml:
<?xml version = "1.0"?> <!doctype hibernate-mapping public " - // hibernate/hibernateマッピングDTD 3.0 // en" "http://hibernate.sourceforge.net/hibernate-mapting-3.0.dtd" <class name = "classes" table = "t_classes" lazy = "false"> <id name = "id"> <generator/generator/> </id> <property name = "name"/> <! - 1対manyマッピング、inverse = "true"は、ピアへの関係を渡すことを意味します - > <enverse = "invers ="> < </class> </hibernate-mapping>
第1レベルのキャッシュの宣言期間は非常に短く、セッションのライフサイクルは一貫しています。第1レベルのキャッシュは、セッションレベルのキャッシュまたは物語レベルのキャッシュとも呼ばれます。最初のレベルのキャッシュはキャッシュオブジェクトであり、属性をキャッシュできません。
テスト方法(同じセッションで2回Load()クエリを使用):
/*それを取り出した後、それはキャッシュに配置され、2回目にcacheから直接取得されます*/ desute sustent =(desute)session.load(desudent.class、1); system.out.println( "sustent.name =" + desudent.getname()); /*クエリステートメントは発行されません、Loadはcache*/ student =(desute)session.load(sustent.class、1)を使用します。 system.out.println( "sustent.name =" + desudent.getname());
注:最初にクエリすると、見つかった結果がセッション、キャッシュ、レベル1のキャッシュに配置されることがわかります。 2回目の時間に時間の値を取得すると、データベースでそれを照会するためにステートメントを発行しませんでしたが、キャッシュから値を直接取得しました(同じセッションにある必要があります)。
テスト方法2(同じセッションで):
学生学生= new Student(); Student.setName( "Zhang San"); serializable id = session.save(desute); Student =(Student)session.load(Student.Class、ID); // save support cache system.out.println( "desudent.name =" + sustent.getName())をサポートするため、クエリステートメントは発行されません。
注:save()メソッドが呼び出され、load()がオブジェクトのロードに使用され、名前属性が実際に取得されますが、データベースを照会するためのステートメントは発行されません。 Save()メソッドもキャッシュをサポートしているためです。
データの大きなバッチの追加をテストします。
public void testcache7(){session session = null; try {session = hibernateutils.getSession(); session.begintransaction(); for(int i = 0; i <100; i ++){sustent sustent = new Student(); Student.setName( "Zhang San" + i); SESSION.SAVE(学生); // 20アイテムごとに更新する場合(i%20 == 0){//キャッシュをクリアし、フラッシュを呼び出した後、データはデータベースsession.flush()に保存されます。 //キャッシュされたコンテンツsession.clear()をクリアします。 }} session.getTransaction()。compid(); } catch(Exception e){e.printstacktrace(); session.getTransaction()。rollback(); }最後に{hibernateutils.closessession(session); }}注記:
1。save()メソッドはキャッシュをサポートするため、問題があります。同時に1,000万個のデータを保存したい場合は、キャッシュに1,000万個のキャッシュオブジェクトがあり、オーバーフローを引き起こす可能性があります。したがって、Hibernateは大規模なデータの更新操作をサポートしていませんが、ループを使用して20個のデータごとにキャッシュをクリアするなど、この問題を非常に柔軟に処理することもできます。
2。保存、更新、saveorupdate、load、get、list、iterate、lockメソッドは、オブジェクトを第1レベルのキャッシュに配置します。第1レベルのキャッシュはキャッシュの数を制御できないため、大きなバッチでデータを操作するときにメモリオーバーフローの可能性に注意を払う必要があります。 evict and clear Methodを使用して、キャッシュ内のコンテンツをクリアできます。
セカンダリキャッシュは、プロセスレベルのキャッシュまたはSessionFactoryレベルのキャッシュとも呼ばれ、セカンダリキャッシュはすべてのセッションキャッシュで共有できます。セカンダリキャッシュのライフサイクルは、SessionFactoryのライフサイクルと同じです。 SessionFactoryは、セカンダリキャッシュを管理できます。読書が書くよりもはるかに大きい場合、二次キャッシュの原理が使用されます。セカンダリキャッシュは、主にエンティティオブジェクトのキャッシュに使用されます。
1.EHCAHE.XMLファイルをSRCディレクトリにコピーします。
2.次のように、キャッシュ製品プロバイダーをhibernate.cfg.xmlファイルに追加します。
<プロパティ名= "hibernate.cache.provider_class"> org.hibernate.cache.ehcacheprovider </property>
3.レベル2キャッシュを有効にします(デフォルトが有効になっているため、スタートアップを表示できません)。
<プロパティ名= "hibernate.cache.use_second_level_cache"> true </property>
4.レベル2キャッシュを使用するエンティティクラスを指定します。
5.キャッシュで使用されるインターフェイスJARパッケージをインポート: lib/optional/ehcache/ehcache-core-2.4.3.jar
ehcache.xmlファイルの内容:
<DefaultCache MaxElementsInmemory = "10000" ETERNAL = "FALSE" TimetOidLeseConds = "120" TimetolivesConds = "120" Overflowtodisk = "true" />
注記:
1.maxelementsinmemoryは、キャッシュ内で最も保存されているオブジェクトを表します。
2.標準は、それが期限切れにならないかどうかを示します(それをfalseに設定することがより実用的です。本当の場合、それが期限切れにならない場合、次の属性は意味がありません)。
3.timetoidLesecodsは、オブジェクトが初めてクリアされた後にアクセスされていない期間を示します。
4。TimetoliveseCodsは、オブジェクトの在庫時間を表します。
5。オーバーフロートディスクは真です。つまり、キャッシュの数はMaxElementsInmemoryで指定された数を超えてディスクに保存されます。
オーバーフローで保存されたディスクパスを指定します。
<ディスクストアパス= "java.io.tmpdir"/>
注:このパスを変更できます。
テスト方法(レベル1キャッシュの前提は、同じセッションにある必要があることです。レベル2キャッシュを使用して、2つの異なるセッションにキャッシュがあるかどうかを確認します):
public void testcache1(){session session = null; try {session = hibernateutils.getSession(); session.begintransaction(); sudints student =(desudent.class、1); out.print.println( "desudent.name =" + desudent.getName(); session.gettransaction() {e.printstacktrace(); session.getTransaction()。rollback();}最後に{hibernateutils.closessession(session);} try {session = hibernateutils.getSession(); session.begintransaction(); desute dusteent =(desution)session。セカンダリキャッシュでデータを共有します。///セカンダリキャッシュはプロセスレベルのキャッシュシステムです。 {hibernateutils.closessession(session);}}注:セカンダリキャッシュが構成されている場合、最初のセッションが閉じられていても、別のセッションがデータをロードすることになっていても、セカンダリキャッシュが構成されているため、データベースのデータを照会するためのステートメントを発行しないことがわかります。
レベル2キャッシュを無効にして、データの大きなバッチの追加を実装します。
public void testcache5(){session session = null; try {session = hibernateutils.getSession(); session.begintransaction(); //ラインファーストキャッシュとセカンダリキャッシュの相互作用は禁止されています。SESTCACHEMODE(CACHEMODE.IGNORE); for(int i = 0; i <100; i ++){sustent sustent = new Student(); Student.setName( "Zhang San" + i); SESSION.SAVE(学生); // 20アイテムごとに更新するif(i%20 == 0){session.flush(); // CACHED CONTENTS SESSION.CLEAR()をクリアします。 }} session.getTransaction()。compid(); } catch(Exception e){e.printstacktrace(); session.getTransaction()。rollback(); }最後に{hibernateutils.closessession(session); }}注:session.flush()は第1レベルのキャッシュをクリアすることを意味しますが、2番目のレベルのキャッシュを再度開始しました。保存した後()、それを第2レベルのキャッシュに保存しますが、過剰なキャッシュによって引き起こされるオーバーフローもあります。したがって、この場合、セカンダリキャッシュを無効にする必要があります。Session.SetCacheMode(cachemode.ignore);
クエリキャッシュ:第1レベルのキャッシュとセカンドレベルのキャッシュキャッシュキャッシュの両方が両方のキャッシュエンティティオブジェクトをキャッシュしますが、特定の属性を取得し、頻繁にデータベースにアクセスするのではなく、キャッシュから取得することを望んでいます。現時点では、クエリキャッシュを使用できます。さらに、エンティティオブジェクトのクエリキャッシュ結果セットはIDをキャッシュします。クエリキャッシュのライフサイクルが変更されます。関連するテーブルが変更されると、クエリキャッシュの宣言サイクルが終了します。これは、セッションのライフサイクルとは何の関係もありません。
1. hibernate.cfg.xmlファイルを変更して、クエリキャッシュを有効にします。 falseがデフォルトである場合、有効になりません。次のように設定する必要があります。
<プロパティ名= "hibernate.cache.use_query_cache"> true </property>
2。次のようなプログラムで有効にする必要があります。
query.setCachable(true)
テスト方法:
public void testcache2(){session session = null; try {session = hibernateutils.getsession(); session.begintransaction(); list names = session.createquery( "Select s.name from Student s").setCacheable(true).List(); (string)names.get(i); system.out.println(name);} session.getTransaction()。compid();} catch(exception e){e.printstacktrace(); session.getTransaction()。rollback();}最後に {HibernateUtils.closeSession(session);}System.out.println("-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- for(int i = 0; i <names.size(); i ++){string name =(string)names.get(i); system.out.println(name.out.println(name.out.println(name.getTransaction()。 {hibernateutils.closessession(session);}}注:上記のコードでは、セカンダリキャッシュをオフにし、クエリキャッシュをオンにしてから、通常のプロパティを照会します。テストコードを実行すると、最初のセッションで最初のクエリがステートメントを発行し、セッションを閉じてから2番目のセッションでクエリを見つけることができます。 2番目のセッションのクエリはステートメントを発行しないことがわかります。つまり、クエリキャッシュはセッションのライフサイクルとは関係ありません。
hibernate.cfg.xmlのキャッシュ構成:
<! - 二次キャッシュを指定するための実装インターフェイスを設定 - > <プロパティ名= "hibernate.cache.region.factory_class"> org.hibernate.cache.ehcacheregionfactory </property> <! - セカンダリキャッシュに使用される構成ファイルを設定します - > <プロパティname = "net.sf.ehcache.configurationresourcename">/ehcache.xml </property> <! - queryを使用してキャッシュを設定 - > <プロパティ名= "hibernate.cache.use_query_cache" <マッピングリソース= "com/lixue/bean/desutent.hbm.xml"/> <! - リソースマッピングファイル(つまり、エンティティマッピングファイル)を導入する必要があります。
上記は、Hibernateキャッシュメカニズムの例のコード分析に関するこの記事のすべての内容です。すべての人に役立つことを願っています。興味のある友人は、このサイトの他の関連トピックを引き続き参照できます。欠点がある場合は、それを指摘するためにメッセージを残してください。このサイトへのご支援をありがとうございました!