検索
ホームページJava&#&チュートリアルJava での MyBatis のクエリとキャッシュ

Java での MyBatis のクエリとキャッシュ

Aug 09, 2017 pm 05:52 PM
javamybatisキャッシュ

クエリ キャッシュの使用は、主にクエリのアクセス速度を向上させることです。この記事では主に MyBatis クエリ キャッシュを紹介します。必要な方は、主にクエリ アクセス速度を向上させるためにクエリ キャッシュを使用することを参考にしてください。ユーザーが毎回データベースクエリの結果データを取得するのではなく、同じデータに対する繰り返しのクエリ処理を簡素化し、アクセス速度を向上させます。

MyBatisのクエリキャッシュメカニズムは、キャッシュ領域のスコープ(ライフサイクル)に応じて、1次キャッシュと2次キャッシュの2種類に分けられます

1. MyBatis の 1 次キャッシュは org.apache.ibatis.cache.impl.PerpetualCache クラスに基づく HashMap ローカル キャッシュであり、そのスコープは Sqlsession です。同じ SQL ステートメントを同じ Sqlsession で 2 回実行すると、最初の実行後、クエリ結果がキャッシュに書き込まれ、2 回目はデータベースにクエリを実行せずにキャッシュからデータが直接取得されるため、クエリの効率が向上します。 Sqlsession が終了すると、Sqlsession 内の 1 次キャッシュは存在しなくなります。 MyBatis の 1 次キャッシュはデフォルトでオンになっており、オフにすることはできません。

1. 1次キャッシュの存在証明

テストクラス:

//证明一级缓存的存在
@Test
public void test01(){
 //第一次查询
 Student student = dao.selectStudentById(2);
 System.out.println(student);
 //第二次查询
 Student student2 = dao.selectStudentById(2);
 System.out.println(student2);  
}

mapper:


<mapper namespace="com.hcx.dao.IStudentDao">  
  <select id=selectStudentById resultType="com.hcx.beans.Student">
   select * from student where id=#{id}
  </select>
</mapper>

実行後、1回だけ実行されたことが判明からDB でクエリを実行すると、2 番目の結果が直接出力されます。 2 回目は Sqlsession キャッシュから読み取られることに注意してください。


2. キャッシュからデータを読み取るための基準は SQL ID です

第 1 レベルのキャッシュは、同じ SQL ステートメントのクエリ結果ではなく、同じ SQL マッピング ID のクエリ結果をキャッシュします。 MyBatis の内部クエリ キャッシュのため、それが第 1 レベルのクエリであっても第 2 レベルのクエリであっても、最下層はハッシュマップを使用して実装されます。キーは SQL の ID 関連コンテンツであり、値はクエリの結果です。データベースから。

マッパー:

rreee

daoインターフェース:

rreee

testクラス:

rreeee

console:sonsolesコンソールを見て、2番目のクエリ結果はまったく同じであることがわかりました。最初のクエリですが、2 番目のクエリはキャッシュからではなく、DB から直接データを読み取りました。これは、キャッシュからデータを読み取る基準がクエリ結果ではなくクエリ SQL のマッピング ID であるためです。


3. 第 1 レベルのクエリ キャッシュに対する追加、削除、および変更の影響

Sqlsession.commit() が送信されたかどうかに関係なく、追加、削除、および変更の操作により、最初のクエリ キャッシュがクリアされます。 -レベルのクエリ キャッシュにより、DB からクエリを再度選択できるようになります。

テストクラス:

<mapper namespace="com.hcx.dao.IStudentDao">
  <select id=selectStudentById resultType="com.hcx.beans.Student">
   select * from student where id=#{id}
  </select>
  <select id="selectStudnetById2" resultType="com.hcx.beans.Student">
   select id,name,age,score,birthday from student where id=#{id}
  </select>
</mapper>
コンソール:


2. 組み込みの二次クエリキャッシュ

MyBatis クエリキャッシュのスコープは、マッピングファイルの名前空間に従って分割されます同じマッパー ネームスペースのマッパークエリデータは同じキャッシュ領域に格納されます。異なる名前空間のデータは相互に干渉しません。
一次キャッシュと二次キャッシュは両方とも名前空間に従って別々に保存されます。ただし、1 次キャッシュと 2 次キャッシュの違いは、Sqlsession が閉じられると、Sqlsession 内のデータは存在しなくなる、つまり 1 次キャッシュも存在しなくなることです。 2 次キャッシュのライフサイクルは、Sqlsession が閉じているかどうかに関係なく、アプリケーション全体と同期されます。

MyBatis はクエリされたオブジェクトではなく SQL ID に基づいてキャッシュからデータを読み取るため、二次キャッシュを使用する目的はデータを共有することではありません。したがって、2 次キャッシュ内のデータは、複数のクエリ間で共有されることを目的としていません (すべてのクエリのクエリ結果にオブジェクトが存在する限り、オブジェクトはキャッシュから直接読み取られます。これがデータの共有です。休止状態でのキャッシュは共有用ですが、MyBatis は共有用ではありません) が、クエリ結果の保存時間を延長し、システム パフォーマンスを向上させるためです。 1. 二次キャッシュの使用

二次キャッシュの使用には、次の 2 つの手順のみが必要です:

エンティティをシリアル化する

マッパー マッピング ファイルに を追加する

1.

では、クエリ結果に関係するエンティティ クラスが java.io.Serializable インターフェイスを実装する必要があります。エンティティ クラスに親クラスがある場合、またはドメイン属性がある場合は、親クラスとドメイン属性クラスもシリアル化インターフェイスを実装する必要があります。

public interface IStudentDao {  
 Student selectStudentById(int id);
 Student selectStudentById2(int id); 
}

2. マッパー マッピング ファイルに タグを追加します

マッパー マッピング ファイルの サブタグを追加します。

//证明从一级缓存中读取数据的依据:
//MyBatis:sql的id+sql语句
//hibernate:查询结果对象的id
@Test
public void test02(){
 Student student = dao.selectStudentById(2);
 System.out.println(student);

 Student student2 = dao.selectStudentById2(2);
 System.out.println(student2);  
}


3. 2次キャッシュの構成

标签添加一些相关属性设置,可以对二级缓存的运行性能进行控制。若不指定设置,则均保持默认值。


<cache eviction="IFIO" flushInterval="10800000"
  readOnly="true" size="512"/>

eviction:逐出策略。当二级缓存中的对象达到最大值时,就需要通过逐出策略将缓存中的对象移出缓存。默认为LRU。常用的策略有FIFO和LRU

flushInterval:刷新缓存的时间间隔,单位毫秒。这里的刷新缓存即清空缓存。一般不指定,即当执行增删改时刷新缓存。

readOnly:设置缓存中数据是否只读。只读的缓存会给所有调用者返回缓存对象的相同实例,因此这些对象不能被修改,这提供了很重要的性能优势。但读写的缓存会返回缓存对象的拷贝。这会慢一些,但是安全,因此默认是false。
size:二级缓存中可以存放的最多对象个数。默认为1024个。

2.二级缓存的存在性证明

对于映射文件中的同一个查询,肯定是同一个namespace中的查询。在一次查询后,将Sqlsession关闭,再进行一次相同查询,发现并没有到DB中进行select查询,说明二级缓存是存在的。


//证明二级缓存的存在
@Test
public void test01(){
 //第一次查询
 Student student = dao.selectStudentById(2);
 System.out.println(student);
 sqlSession.close();
 sqlSession = MyBatisUtils.getSqlSession();
 dao = sqlSession.getMapper(IStudentDao.class);
 //第二次查询
 Student student2 = dao.selectStudentById(2);
 System.out.println(student2);  
}

查看控制台:

Cache Hit Ratio表示缓存命中率。开启二级缓存后,每执行一次查询,系统都会计算一次二级缓存的命中率。第一次查询也是先从缓存中查询,只不过缓存中一定是没有的。所以会再从DB中查询。由于二级缓存中不存在该数据,所以命中率为0.但第二次查询是从二级缓存中读取的,所以这一次的命中率为1/2=0.5。当然,若有第三次查询,则命中率为1/3=0.66

3.增删改对二级缓存的影响

增删改操作,无论是否进行提交sqlSession.commit(),均会清空一级、二级缓存,使查询再次从DB中select。

测试类:


@Testpublic void test02(){
 //第一次查询
 Student student = dao.selectStudentById(2);
 System.out.println(student);
 sqlSession.close();
 sqlSession = MyBatisUtils.getSqlSession();
 dao = sqlSession.getMapper(IStudentDao.class);
 //插入
 dao.insertStudent(new Student("",0,0));
 //第二次查询
 Student student2 = dao.selectStudentById(2);
 System.out.println(student2);  
}

控制台:

注意,在第二次查询时的缓存命中率为0.5,但还是从DB中查询了。说明在缓存中与该查询相对应的key是存在的,但其value被清空。而value被清空的原因是前面执行了对DB的增删改操作,所以不会从缓存中直接将null值返回,而是从DB中进行查询。

说明:

二级缓存的清空,实质上是对所查找key对应的value置为null,而非将对,即entry对象删除。

从DB中进行select查询的条件是:缓存中根本不存在这个key或者缓存中存在该key所对应的entry对象,但value为null。

设置增删改操作不刷新二级缓存:

若要使某个增、删或改操作不清空二级缓存,则需要在其中添加属性flushCache="false",默认为true。


<insert id="insertStudent" flushCache="false">
  insert into student(name,age,score) values(#{name},#{age},#{score})
 </insert>

4.二级缓存的关闭

二级缓存默认为开启状态。若要将其关闭,则需要进行相关设置。
根据关闭的范围大小,可以分为全局关闭和局部关闭

1.全局关闭(在配置文件中设置)

全局关闭是指整个应用的二级缓存全部关闭,所有查询均不使用二级缓存。全局开关设置在主配置文件的全局设置中,该属性为cacheEnabled,设置为false,则关闭;设置为true,则开启,默认值为true。即二级缓存默认是开启的。


<!-- 关闭二级缓存 -->
<settings>
 <setting name="cacheEnabled" value="false"/>
</settings>

2.局部关闭(在映射文件的每个select中设置)

局部关闭指整个应用的二级缓存是开启的,但只是针对某个查询,不使用二级缓存。此时可以单独只关闭该标签的二级缓存。

在该要关闭二级缓存的标签中,将其属性useCache设置为false,即可关闭该查询的二级缓存。该属性默认为true,即每个查询的二级缓存默认是开启的。


<!--useCache="false"对当前sql的二级缓存的局部关闭 -->
 <select id=selectStudentById useCache="false" resultType="com.hcx.beans.Student">
  select * from student where id=#{id}
 </select>

5.二级缓存的使用原则

1.只能在一个命名空间下使用二级缓存

由于二级缓存中的数据是基于namespace的,即不同namespace中的数据互不干扰。在多个namespace中若均存在对同一个表的操作,那么这多个namespace中的数据可能就会出现不一致现象。

2.在单表上使用二级缓存

如果一个表与其它表有关联关系,那么久非常有可能存在多个namespace对同一数据的操作。而不同namespace中的数据互补干扰,所以就有可能出现多个namespace中的数据不一致现象。

3.查询多于修改时使用二级缓存

在查询操作远远多于增删改操作的情况下可以使用二级缓存。因为任何增删改操作都将刷新二级缓存,对二级缓存的频繁刷新将降低系统性能。

三、ehcache二级查询缓存

MyBatis允许使用第三方缓存产品。ehCache就是其中一种。

注意:使用ehcache二级缓存,实体类无需实现序列化接口。

1.导入jar包

2.添加ehcache.xml

解压ehcache的核心jar包ehcache-core-2.6.8.jar,将其中的一个配置文件ehcache-failsafe.xml直接放到项目的src目录下,并更名为ehcache.xml

(1)标签

指定一个文件目录,当内存空间不够,需要将二级缓存中数据写到硬盘上时,会写到这个指定目录中。其值一般为java.io.tmpdir,表示当前系统的默认文件临时目录。

当前文件系统的默认文件临时目录,可以通过System.property()方法查看:


@Test
public void test(){
 String path = System.getProperty("java.io.tmpdir");
 System.out.println(path);
}

(2)标签

3.启用ehcache缓存机制

在映射文件的mapper中的中通过type指定缓存机制为Ehcache缓存。默认为MyBatis内置的二级缓存org.apache.ibatis.cache.impl.PerpetualCache。


<mapper namespace="com.hcx.dao.IStudentDao">
 <cache type="org.mybatis.caches.ehcache.EhcacheCache"/>
  <select id=selectStudentById resultType="com.hcx.beans.Student">
   select * from student where id=#{id}
  </select>
</mapper>

4.ehcache在不同mapper中的个性化设置

在ehcache.xml中设置的属性值,会对该项目中所有使用ehcache缓存机制的缓存区域起作用。一个项目中可以有多个mapper,不同的mapper有不同的缓存区域。对于不同缓存区域也可进行专门针对于当前区域的个性设置,可通过指定不同mapper的属性值来设置。

属性值的优先级高于ehcache.xml中的属性值。


<mapper namespace="com.hcx.dao.IStudentDao">
 <cache type="org.mybatis.caches.ehcache.EhcacheCache"/>
   <property name="maxElementsInMemory" value="5000"/>
   <property name="timeToIdleSeconds" value="240"/>
 </cache>
</mapper>

以上がJava での MyBatis のクエリとキャッシュの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
高度なJavaプロジェクト管理、自動化の構築、依存関係の解像度にMavenまたはGradleを使用するにはどうすればよいですか?高度なJavaプロジェクト管理、自動化の構築、依存関係の解像度にMavenまたはGradleを使用するにはどうすればよいですか?Mar 17, 2025 pm 05:46 PM

この記事では、Javaプロジェクト管理、自動化の構築、依存関係の解像度にMavenとGradleを使用して、アプローチと最適化戦略を比較して説明します。

適切なバージョン化と依存関係管理を備えたカスタムJavaライブラリ(JARファイル)を作成および使用するにはどうすればよいですか?適切なバージョン化と依存関係管理を備えたカスタムJavaライブラリ(JARファイル)を作成および使用するにはどうすればよいですか?Mar 17, 2025 pm 05:45 PM

この記事では、MavenやGradleなどのツールを使用して、適切なバージョン化と依存関係管理を使用して、カスタムJavaライブラリ(JARファイル)の作成と使用について説明します。

カフェインやグアバキャッシュなどのライブラリを使用して、Javaアプリケーションにマルチレベルキャッシュを実装するにはどうすればよいですか?カフェインやグアバキャッシュなどのライブラリを使用して、Javaアプリケーションにマルチレベルキャッシュを実装するにはどうすればよいですか?Mar 17, 2025 pm 05:44 PM

この記事では、カフェインとグアバキャッシュを使用してJavaでマルチレベルキャッシュを実装してアプリケーションのパフォーマンスを向上させています。セットアップ、統合、パフォーマンスの利点をカバーし、構成と立ち退きポリシー管理Best Pra

キャッシュや怠zyなロードなどの高度な機能を備えたオブジェクトリレーショナルマッピングにJPA(Java Persistence API)を使用するにはどうすればよいですか?キャッシュや怠zyなロードなどの高度な機能を備えたオブジェクトリレーショナルマッピングにJPA(Java Persistence API)を使用するにはどうすればよいですか?Mar 17, 2025 pm 05:43 PM

この記事では、キャッシュや怠zyなロードなどの高度な機能を備えたオブジェクトリレーショナルマッピングにJPAを使用することについて説明します。潜在的な落とし穴を強調しながら、パフォーマンスを最適化するためのセットアップ、エンティティマッピング、およびベストプラクティスをカバーしています。[159文字]

Javaのクラスロードメカニズムは、さまざまなクラスローダーやその委任モデルを含むどのように機能しますか?Javaのクラスロードメカニズムは、さまざまなクラスローダーやその委任モデルを含むどのように機能しますか?Mar 17, 2025 pm 05:35 PM

Javaのクラスロードには、ブートストラップ、拡張機能、およびアプリケーションクラスローダーを備えた階層システムを使用して、クラスの読み込み、リンク、および初期化が含まれます。親の委任モデルは、コアクラスが最初にロードされ、カスタムクラスのLOAに影響を与えることを保証します

分散コンピューティングにJavaのRMI(リモートメソッドの呼び出し)を使用するにはどうすればよいですか?分散コンピューティングにJavaのRMI(リモートメソッドの呼び出し)を使用するにはどうすればよいですか?Mar 11, 2025 pm 05:53 PM

この記事では、分散アプリケーションを構築するためのJavaのリモートメソッドの呼び出し(RMI)について説明します。 インターフェイスの定義、実装、レジストリのセットアップ、およびクライアント側の呼び出しを詳述し、ネットワークの問題やセキュリティなどの課題に対処します。

ネットワーク通信にJavaのソケットAPIを使用するにはどうすればよいですか?ネットワーク通信にJavaのソケットAPIを使用するにはどうすればよいですか?Mar 11, 2025 pm 05:53 PM

この記事では、ネットワーク通信のためのJavaのソケットAPI、クライアントサーバーのセットアップ、データ処理、リソース管理、エラー処理、セキュリティなどの重要な考慮事項をカバーしています。 また、パフォーマンスの最適化手法も調査します

Javaでカスタムネットワークプロトコルを作成するにはどうすればよいですか?Javaでカスタムネットワークプロトコルを作成するにはどうすればよいですか?Mar 11, 2025 pm 05:52 PM

この記事では、カスタムJavaネットワーキングプロトコルの作成を詳述しています。 プロトコルの定義(データ構造、フレーミング、エラー処理、バージョン化)、実装(ソケットを使用)、データシリアル化、およびベストプラクティス(効率、セキュリティ、メンテナ

See all articles

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

AIヘンタイを無料で生成します。

ホットツール

mPDF

mPDF

mPDF は、UTF-8 でエンコードされた HTML から PDF ファイルを生成できる PHP ライブラリです。オリジナルの作者である Ian Back は、Web サイトから「オンザフライ」で PDF ファイルを出力し、さまざまな言語を処理するために mPDF を作成しました。 HTML2FPDF などのオリジナルのスクリプトよりも遅く、Unicode フォントを使用すると生成されるファイルが大きくなりますが、CSS スタイルなどをサポートし、多くの機能強化が施されています。 RTL (アラビア語とヘブライ語) や CJK (中国語、日本語、韓国語) を含むほぼすべての言語をサポートします。ネストされたブロックレベル要素 (P、DIV など) をサポートします。

SublimeText3 Linux 新バージョン

SublimeText3 Linux 新バージョン

SublimeText3 Linux 最新バージョン

MantisBT

MantisBT

Mantis は、製品の欠陥追跡を支援するために設計された、導入が簡単な Web ベースの欠陥追跡ツールです。 PHP、MySQL、Web サーバーが必要です。デモおよびホスティング サービスをチェックしてください。

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

Safe Exam Browser

Safe Exam Browser

Safe Exam Browser は、オンライン試験を安全に受験するための安全なブラウザ環境です。このソフトウェアは、あらゆるコンピュータを安全なワークステーションに変えます。あらゆるユーティリティへのアクセスを制御し、学生が無許可のリソースを使用するのを防ぎます。