재인쇄할 소스를 표시해 주세요:
앞서 언급한 대로: Spring+SpringMVC+MyBatis 심층 학습 및 구성(7) - MyBatis 지연 로딩
mybatis는 데이터베이스 부담을 줄이기 위해 쿼리 캐시를 제공합니다. , 데이터베이스 성능을 향상시킵니다.
mybatis는 1단계 캐시와 2단계 캐시를 제공합니다.
첫 번째 수준 캐시는 SqlSession 수준 캐시입니다. 데이터베이스를 운영할 때 sqlSession 객체를 생성해야 합니다. 객체에는 캐시 데이터를 저장하기 위한 데이터 구조(HashMap)가 있습니다. 서로 다른 sqlSession 간의 캐시 데이터 영역(HashMap)은 서로 영향을 미치지 않습니다.
두 번째 수준 캐시는 매퍼 수준 캐시입니다. 여러 sqlSession은 동일한 Mapper의 sql 문을 작동합니다. 두 번째 수준 캐시는 sqlSession에 걸쳐 있습니다.
캐싱을 사용하는 이유는 무엇인가요?
캐시에 데이터가 있으면 데이터베이스에서 데이터를 가져올 필요가 없으므로 시스템 성능이 크게 향상됩니다.
처음으로 사용자 ID가 1인 사용자 정보에 대한 쿼리를 시작하는 경우 먼저 ID가 1인 사용자 정보가 있는지 확인합니다. 캐시가 아닌 경우 데이터베이스에서 사용자 정보를 쿼리합니다.
사용자 정보를 가져오고 첫 번째 수준 캐시에 사용자 정보를 저장합니다.
sqlSession이 커밋 작업(삽입, 업데이트, 삭제 수행)을 수행하는 경우 sqlSession에서 첫 번째 수준 캐시를 삭제합니다. 이 작업의 목적은 캐시에 최신 정보를 저장하고 더티 읽기를 방지하는 것입니다.
두 번째로 사용자 ID 1의 사용자 정보를 쿼리하기 위해 전송되며, 먼저 캐시에 ID 1의 사용자 정보가 있는지 확인하고, 캐시에 사용자 정보를 직접 가져옵니다.
Mybatis는 기본적으로 레벨 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(); }
은 mybatis와 spring을 통합하여 공식 개발되었으며, 트랜잭션은 서비스에서 제어됩니다.
서비스 메소드에는 많은 Mapper 메소드 호출이 포함됩니다.
service{
//실행 시작 시 트랜잭션을 시작하고 SqlSession 객체를 생성합니다
//처음 매퍼 메소드 findUserById(1)가 호출될 때
//두 번째 매퍼 메소드 findUserById( 1) 호출되면 1단계 캐시에서 데이터를 가져옵니다
//메소드가 종료되고 sqlSession이 닫힙니다
}
동일한 사용자 정보를 쿼리하기 위해 두 개의 서비스 호출이 실행되는 경우 1단계 캐시는 사용되지 않습니다. , 세션 메서드가 종료되고 sqlSession이 닫히기 때문입니다.
먼저 mybatis의 2차 캐시를 활성화하세요.
sqlSession1은 사용자 ID 1로 사용자 정보를 쿼리합니다. 사용자 정보를 쿼리한 후 쿼리 데이터가 2차 캐시에 저장되어 있다는 것을 후회합니다.
sqlSession3이 동일한 매퍼에서 SQL을 실행하고 커밋 제출을 실행하면 매퍼 아래의 2차 캐시 영역에 있는 데이터가 지워집니다.
sqlSession2는 사용자 ID가 1인 사용자 정보를 쿼리하여 캐시에 데이터가 있는지 확인하고, 데이터가 있으면 캐시에서 직접 가져옵니다.
두 번째 수준 캐시와 첫 번째 수준 캐시의 차이점은 두 번째 수준 캐시의 범위가 더 크고 여러 sqlSession이 UserMapper의 두 번째 수준 캐시 영역을 공유할 수 있다는 것입니다. UserMapper에는 두 번째 수준 캐시 영역(네임스페이스로 구분됨)이 있고 다른 매퍼에도 자체적인 두 번째 수준 캐시 영역(네임스페이스로 구분됨)이 있습니다.
각 네임스페이스 매퍼에는 두 번째 수준 캐시 영역이 있습니다. 두 매퍼의 네임스페이스가 동일한 경우 SQL 쿼리를 실행하는 두 매퍼에서 얻은 데이터는 동일한 두 번째 수준 캐시 영역에 저장됩니다.
mybatis의 두 번째 수준 캐시는 SqlMapConfig.xml에서 두 번째 수준 캐시의 기본 스위치를 설정하는 것 외에도 두 번째 수준도 활성화해야 합니다. 특정 mapper.xml에 캐시합니다.
핵심 구성 파일 SqlMapConfig.xml에 추가:
<setting name="cacheEnabled" value="true"/>
Description |
허용 값 |
기본값 |
|
cacheEnabled |
바로 여기 있습니다. 구성 파일 아래의 캐시는 전역적으로 켜거나 끌 수 있습니다. |
참 거짓 |
참 |
在UserMapper.xml中开启二级缓存,UserMapper.xml下的sql执行完成后存储在它的缓存区域(HashMap)。
为了将缓存数据取出执行反序列划操作,因为二级缓存数据存储介质多种多样,不一定在内存。可能在硬盘、远程等。
@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(); }
在statement中设置useCache=false可以禁用当前select语句的二级缓存,即每次查询都会发出sql,默认情况是true,即该sql使用二级缓存。
在mapper的同一个namespace中,如果有其它insert、update、delete操作数据后需要刷新缓存,如果不执行刷新缓存会出现脏读。
设置statement配置中的flushCache="true"属性,默认情况下为true即刷新缓存,如果改成false则不会刷新。使用缓存时如果手动修改数据库表中的查询数据会出现脏读。
总结:一般情况下执行完commit操作都需要刷新缓存,flushCache=true表示刷新缓存,这样可以避免数据库脏读。
flushInterval(刷新间隔)可以被设置为任意的正整数,而且它们代表一个合理的毫秒形式的时间端。默认情况是不设置,也局势没有刷新间隔,缓存仅仅调用语句时刷新。
size(引用数目)可以被设置为任意正整数,要记住你缓存的对象数目和你运行环境的可用内存资源数目。默认值是1024。
readOnly(只读)属性可以被设置为true或false。只读的缓存会给所有调用者返回缓存对象的相同实例。因此这些对象不能被修改。这提供了很重要的性能优势。可读写的缓存会返回缓存对象的拷贝(通过序列化)。这会慢一些,但是安全,因此默认是false。
如下例子:
这个更高级的配置创建了一个 FIFO 缓存,并每隔 60 秒刷新,存数结果对象或列表的 512 个引用,而且返回的对象被认为是只读的,因此在不同线程中的调用者之间修改它们会导致冲突。可用的收回策略有, 默认的是 LRU:
LRU – 最近最少使用的:移除最长时间不被使用的对象。
FIFO – 先进先出:按对象进入缓存的顺序来移除它们。
SOFT – 软引用:移除基于垃圾回收器状态和软引用规则的对象。
WEAK – 弱引用:更积极地移除基于垃圾收集器状态和弱引用规则的对象。
ehcache是一个纯Java的进程内缓存框架,是一种广泛使用的开源Java分布式缓存,具有快速、精干等特点,是Hibernate中默认的CacheProvider。
为了提高系统并发、性能,一般会系统进行分布式部署(集群部署方式)
不使用分布式缓存,缓存的数据在各个服务单独存储,不方便系统开发。所以要使用分布式缓存对缓存数据进行集中管理。
mybatis的特长是sql操作,缓存数据的管理不是mybatis的特长。mybatis无法实现分布式缓存,需要和其它分布式缓存框架进行整合,如:redis、memcached、ehcache等。
mybatis提供了一个cache接口,如果要实现自己的缓存逻辑,实现cache接口开发即可。
mybatis和ehcache整合,mybatis和ehcache整合包中提供了一个cache接口的实现类。
mybatis默认的cache实现类是:
配置mapper中cache中的type为ehcache对cache接口的实现类型。
在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에 캐시된 데이터에 대한 두 번의 액세스 사이의 시간이 timeToIdleSeconds 속성 값을 초과하면 데이터가 삭제됩니다. 기본값은 유휴 시간입니다. 무한대.
timeToLiveSeconds: 캐시 요소의 유효 수명은 0입니다. 이는 요소 생존 시간이 무한함을 의미합니다.
diskSpoolBufferSizeMB: 이 매개변수는 DiskStore(디스크 캐시)의 버퍼 크기를 설정합니다. 기본값은 30MB이며, 각 캐시에는 자체 버퍼가 있어야 합니다.
diskPertant: VM이 다시 시작될 때 디스크가 EhCache에 데이터를 저장할 수 있는지 여부입니다.
diskExpiryThreadIntervalSeconds - 디스크 캐시 정리 스레드 실행 간격이며 기본값은 120초입니다. 120초마다 해당 스레드가 EhCache의 데이터를 정리합니다.
memoryStoreEvictionPolicy - 메모리 캐시가 최대치에 도달하고 새 요소가 추가되면 캐시에서 요소를 제거하는 정책입니다. 기본값은 LRU(최근에 가장 적게 사용됨)이고 옵션은 LFU(가장 덜 자주 사용됨) 및 FIFO(선입선출)입니다.
3.4와 동일
액세스 횟수가 많고 사용자가 실시간 쿼리 결과에 대한 요구 사항이 높지 않은 경우 mybatis L2 캐시 기술을 사용하여 데이터베이스 액세스를 줄일 수 있습니다. . 시간이 많이 소요되는 통계 분석 SQL, 전화 요금 조회 SQL 등과 같은 비즈니스 시나리오, 액세스 속도를 향상시킵니다.
구현 방법은 다음과 같습니다. 새로 고침 간격을 설정하면 mybatis가 일정한 간격으로 자동으로 캐시를 지우고, 30분, 60분으로 설정하는 등 데이터 변경 빈도에 따라 캐시 새로 고침 간격인 flashInterval을 설정합니다. 필요에 따라 24시간 등.
Mybatis 2차 캐시는 다음과 같은 세밀한 데이터 레벨 캐싱에 적합하지 않습니다. 제품 정보 캐싱 횟수가 많아 사용자가 필요합니다. 이때, 마이바티스의 2차 캐시를 사용하면, 제품이 변경될 때 해당 제품의 캐시 정보만 갱신하고, 다른 제품의 정보는 갱신하지 않기 때문에 이를 달성할 수 없습니다. mybatis의 2차 캐시 영역은 매퍼에 있습니다. 상품 정보가 변경되면 모든 상품 정보의 캐시된 데이터가 모두 삭제됩니다. 이러한 문제를 해결하려면 비즈니스 계층에서 필요에 따라 타겟 방식으로 데이터를 캐시해야 합니다.
이 글이 도움이 되셨다면 위챗으로 팁 부탁드려요~
위 내용은 쿼리 캐시란 무엇입니까? MyBatis 쿼리 캐시 사용법 소개의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!