転載する場合は出典を明記してください:
前述の通り: Spring+SpringMVC+MyBatis の徹底学習と構築 (7) - MyBatis の遅延読み込み
1. クエリ キャッシュとは
mybatis はデータベースの負荷を軽減するためにクエリ キャッシュを提供します。 、データベースのパフォーマンスが向上します。
mybatis は、一次キャッシュと二次キャッシュを提供します。
1次キャッシュはSqlSessionレベルのキャッシュです。データベースを操作する際には、sqlSessionオブジェクトを構築する必要があり、そのオブジェクト内にキャッシュデータを格納するためのデータ構造体(HashMap)が存在します。異なるsqlSession間のキャッシュデータ領域(HashMap)は相互に影響しません。
2 次キャッシュはマッパーレベルのキャッシュです。複数の sqlSession は同じマッパーの SQL ステートメントを操作します。2 次キャッシュは sqlSession にまたがります。
なぜキャッシュを使用するのですか?
キャッシュにデータがある場合、データベースからデータを取得する必要がないため、システムのパフォーマンスが大幅に向上します。
2. 一次キャッシュ
2.1 一次キャッシュの動作原理
ユーザー ID 1 のユーザー情報のクエリを初めて開始するときは、まず、ID 1 のユーザー情報が存在するかどうかを確認します。キャッシュされていない場合は、データベースからユーザー情報を照会します。
ユーザー情報を取得し、ユーザー情報を一次キャッシュに保存します。
sqlSession がコミット操作 (挿入、更新、削除の実行) を実行する場合、sqlSession の 1 次キャッシュをクリアします。これは、最新の情報をキャッシュに保存し、ダーティ リードを回避するためです。
ユーザー ID 1 のユーザー情報をクエリするために 2 回目に送信されるときは、まずキャッシュに ID 1 のユーザー情報があるかどうかを調べます。キャッシュに存在する場合は、キャッシュからユーザー情報を直接取得します。
2.2 レベル 1 キャッシュ テスト
Mybatis はデフォルトでレベル 1 キャッシュをサポートしており、構成ファイルで構成する必要はありません。
上記の 1 次キャッシュの原則の手順に従ってテストしてください。
@Testpublic void testCache1() throws Exception{
SqlSession sqlSession=sqlSessionFactory.openSession();
UserMapper userMapper=sqlSession.getMapper(UserMapper.class);//下边查询使用一个SqlSession//第一次发起请求,查询id为1的用户User user1=userMapper.findUserById(1);
System.out.println(user1); //如果sqlSession去执行commit操作(执行插入、更新、删除),清空sqlSession中的一级缓存,//这样做的目的是为了让缓存中存储的是最新的信息,避免脏读。//更新user1的信息user1.setUsername("测试用户22");
userMapper.updateUser(user1);//执行commit操作去清空缓存 sqlSession.commit(); //第二次发起请求,查询id为1的用户User user2=userMapper.findUserById(1);
System.out.println(user2);
sqlSession.close();
}
ログイン後にコピー
2.3 レベル1キャッシュアプリケーション
はmybatisとspringを統合して正式に開発されており、トランザクションはサービス内で制御されている。
サービス メソッドには、多数の Mapper メソッド呼び出しが含まれています。
service{
//実行開始時にトランザクションを開始し、SqlSessionオブジェクトを作成します
//1回目はマッパーメソッドfindUserById(1)が呼び出されます
//2回目はマッパーメソッドfindUserById( 1) is call , fetch data from the 1次キャッシュ
//メソッドが終了し、sqlSessionがクローズされる
}
同じユーザー情報を問い合わせるために2つのサービスコールが実行された場合、1次キャッシュは使用されませんセッションメソッドが終了し、sqlSession が閉じられるため、第 1 レベルのキャッシュがクリアされます。
3. 2次キャッシュ
3.1 2次キャッシュの原理
まずmybatisの2次キャッシュを有効にします。
sqlSession1 は、ユーザー ID 1 のユーザー情報をクエリします。ユーザー情報をクエリした後、クエリ データは 2 次キャッシュに格納されます。
sqlSession3が同一マッパー配下でSQLを実行し、コミットサブミットを実行すると、マッパー配下の2次キャッシュ領域のデータはクリアされます。
sqlSession2 は、ユーザー ID 1 のユーザー情報をクエリし、キャッシュにデータが存在するかどうかを確認し、存在する場合はキャッシュからデータを直接取得します。
2次キャッシュと1次キャッシュの違い: 2次キャッシュの範囲が広く、複数のsqlSessionでUserMapperの2次キャッシュ領域を共有できます。 UserMapper には 2 次キャッシュ領域 (名前空間で分割) があり、他のマッパーにも独自の 2 次キャッシュ領域 (名前空間で分割) があります。
各名前空間マッパーには 2 次キャッシュ領域があります。2 つのマッパーの名前空間が同じ場合、SQL クエリを実行する 2 つのマッパーによって取得されたデータは同じ 2 次キャッシュ領域に格納されます。
3.2 二次キャッシュをオンにする
mybatis の二次キャッシュは、SqlMapConfig.xml で二次キャッシュのメイン スイッチを設定することに加えて、二次キャッシュも有効にする必要があります。特定のmapper.xmlにキャッシュします。
コア構成ファイル SqlMapConfig.xml に追加します:
<setting name="cacheEnabled" value="true"/>
ログイン後にコピー
|
説明 |
許可される値 |
デフォルト値 |
cacheEnabled
はここにあります すべて構成ファイル内のキャッシュはグローバルにオン/オフを切り替えることができます。 |
真偽 |
真 |
|
在UserMapper.xml中开启二级缓存,UserMapper.xml下的sql执行完成后存储在它的缓存区域(HashMap)。
3.3调用pojo类实现序列化接口
为了将缓存数据取出执行反序列划操作,因为二级缓存数据存储介质多种多样,不一定在内存。可能在硬盘、远程等。
3.4测试方法
@Testpublic void testCache2() throws Exception{
SqlSession sqlSession1=sqlSessionFactory.openSession();
SqlSession sqlSession2=sqlSessionFactory.openSession();
SqlSession sqlSession3=sqlSessionFactory.openSession();
UserMapper userMapper1=sqlSession1.getMapper(UserMapper.class);
UserMapper userMapper2=sqlSession2.getMapper(UserMapper.class);
UserMapper userMapper3=sqlSession3.getMapper(UserMapper.class); //第一次发起请求,查询id为1的用户User user1=userMapper1.findUserById(1);
System.out.println(user1);//这里执行关闭操作,将sqlSession中的数据写到二级缓存区域 sqlSession1.close(); //使用sqlSession3执行commit()操作User user=userMapper3.findUserById(1);
user1.setUsername("Joanna");
userMapper3.updateUser(user);//执行提交,清空UserMapper下边的二级缓存 sqlSession3.commit();
sqlSession3.close(); //第二次发起请求,查询id为1的用户User user2=userMapper2.findUserById(1);
System.out.println(user2);
sqlSession2.close();
}
ログイン後にコピー
3.5禁用二级缓存
在statement中设置useCache=false可以禁用当前select语句的二级缓存,即每次查询都会发出sql,默认情况是true,即该sql使用二级缓存。
3.6刷新缓存(就是清空缓存)
在mapper的同一个namespace中,如果有其它insert、update、delete操作数据后需要刷新缓存,如果不执行刷新缓存会出现脏读。
设置statement配置中的flushCache="true"属性,默认情况下为true即刷新缓存,如果改成false则不会刷新。使用缓存时如果手动修改数据库表中的查询数据会出现脏读。
flushCache="true">
总结:一般情况下执行完commit操作都需要刷新缓存,flushCache=true表示刷新缓存,这样可以避免数据库脏读。
3.7 Mybatis Cache参数
flushInterval(刷新间隔)可以被设置为任意的正整数,而且它们代表一个合理的毫秒形式的时间端。默认情况是不设置,也局势没有刷新间隔,缓存仅仅调用语句时刷新。
size(引用数目)可以被设置为任意正整数,要记住你缓存的对象数目和你运行环境的可用内存资源数目。默认值是1024。
readOnly(只读)属性可以被设置为true或false。只读的缓存会给所有调用者返回缓存对象的相同实例。因此这些对象不能被修改。这提供了很重要的性能优势。可读写的缓存会返回缓存对象的拷贝(通过序列化)。这会慢一些,但是安全,因此默认是false。
如下例子:
这个更高级的配置创建了一个 FIFO 缓存,并每隔 60 秒刷新,存数结果对象或列表的 512 个引用,而且返回的对象被认为是只读的,因此在不同线程中的调用者之间修改它们会导致冲突。可用的收回策略有, 默认的是 LRU:
LRU – 最近最少使用的:移除最长时间不被使用的对象。
FIFO – 先进先出:按对象进入缓存的顺序来移除它们。
SOFT – 软引用:移除基于垃圾回收器状态和软引用规则的对象。
WEAK – 弱引用:更积极地移除基于垃圾收集器状态和弱引用规则的对象。
4.mybatis整合ehcache
ehcache是一个纯Java的进程内缓存框架,是一种广泛使用的开源Java分布式缓存,具有快速、精干等特点,是Hibernate中默认的CacheProvider。
4.1分布式缓存
为了提高系统并发、性能,一般会系统进行分布式部署(集群部署方式)
不使用分布式缓存,缓存的数据在各个服务单独存储,不方便系统开发。所以要使用分布式缓存对缓存数据进行集中管理。
mybatis的特长是sql操作,缓存数据的管理不是mybatis的特长。mybatis无法实现分布式缓存,需要和其它分布式缓存框架进行整合,如:redis、memcached、ehcache等。
4.2整合方法(掌握)
mybatis提供了一个cache接口,如果要实现自己的缓存逻辑,实现cache接口开发即可。
mybatis和ehcache整合,mybatis和ehcache整合包中提供了一个cache接口的实现类。
mybatis默认的cache实现类是:
4.3加入ehcache包
4.4整合ehcache
配置mapper中cache中的type为ehcache对cache接口的实现类型。
4.5加入ehcache的配置文件
在classpath下配置ehcache.xml
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:noNamespaceSchemaLocation="../config/ehcache.xsd"><diskStore path="F:\develop\ehcache" /><defaultCache maxElementsInMemory="1000"
maxElementsOnDisk="10000000"eternal="false"
overflowToDisk="false"
timeToIdleSeconds="120"timeToLiveSeconds="120"
diskExpiryThreadIntervalSeconds="120"memoryStoreEvictionPolicy="LRU"></defaultCache></ehcache>
ログイン後にコピー
属性の説明:
diskStore: ディスク上のデータの保存場所を指定します。
defaultCache: CacheManager.add (「demoCache」) でキャッシュを作成するとき、EhCache は で指定された管理戦略を採用します。
以下のプロパティが必要です:
maxElementsInMemory: メモリにキャッシュされる要素の最大数。
maxElementsOnDisk: ディスク上にキャッシュされる要素の最大数 (0 が無限を意味する場合)。
eternal: キャッシュされた要素が期限切れにならないかどうかを設定します。 true の場合、キャッシュされたデータは常に有効です。 false の場合、timeToIdleSeconds と timeToLiveSeconds に基づいて判断する必要があります。
overflowToDisk: メモリ キャッシュがオーバーフローしたときに、期限切れの要素をディスクにキャッシュするかどうかを設定します。
以下の属性はオプションです:
timeToIdleSeconds: EhCache にキャッシュされたデータへの 2 回のアクセス間の時間が timeToIdleSeconds 属性の値を超えると、データは削除されます。デフォルト値は 0 (アイドル時間) です。巨大。
timeToLiveSeconds: キャッシュ要素の有効期間はデフォルトは 0 で、要素の生存時間が無限であることを意味します。
diskSpoolBufferSizeMB: このパラメータは、DiskStore (ディスク キャッシュ) のバッファ サイズを設定します。デフォルトは 30MB で、各キャッシュには独自のバッファーが必要です。
diskPersistent: VM の再起動時にディスクが EhCache にデータを保存できるようにするかどうか。デフォルトは false です。
diskExpiryThreadIntervalSeconds - ディスク キャッシュ クリーニング スレッドの実行間隔。デフォルトは 120 秒です。 120 秒ごとに、対応するスレッドが EhCache 内のデータを消去します。
memoryStoreEvictionPolicy - メモリ キャッシュが最大値に達し、新しい要素が追加された場合に、キャッシュから要素を削除するポリシー。デフォルトは LRU (最も最近使用されていない) で、オプションは LFU (最も頻繁に使用されていない) および FIFO (先入れ先出し) です。
4.6 テスト プログラム
3.4 と同じ
4.7 L2 キャッシュ アプリケーション シナリオ
アクセス数が多く、ユーザーがリアルタイムのクエリ結果に対する高い要件を持たないクエリ リクエストの場合、mybatis L2 キャッシュ テクノロジを使用してデータベース アクセスを削減できます。アクセス速度の向上: 時間のかかる統計分析 SQL、電話料金クエリ SQL などのビジネス シナリオ。
実装方法は以下の通りです。リフレッシュ間隔を設定することで、mybatisが定期的にキャッシュを自動的にクリアし、データ変更の頻度に応じてキャッシュのリフレッシュ間隔flushIntervalを30分、60分、60分などに設定します。 24時間などニーズに応じて対応します。
4.8 二次キャッシュの制限事項
Mybatis の二次キャッシュは、次の要件などのきめ細かいデータ レベルのキャッシュには適していません: 製品情報のキャッシュ 多数の製品情報クエリのアクセスがあるため、ユーザーは必要です。現時点で、mybatis の 2 次キャッシュを使用している場合、製品が変更されたときにこの製品のキャッシュ情報のみを更新し、他の製品の情報を更新することはできません。 mybatisの2次キャッシュ領域はマッパー内にあり、商品情報が変更されると、全商品情報のキャッシュデータが全てクリアされます。このような問題を解決するには、ビジネス層はニーズに基づいて対象を絞った方法でデータをキャッシュする必要があります。
この記事が役に立ったら、WeChat で私にヒントを送ってください~
以上がクエリキャッシュとは何ですか? MyBatis クエリ キャッシュの使用法の概要の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。