>  기사  >  Java  >  mybatis의 캐시 예제에 대한 자세한 설명

mybatis의 캐시 예제에 대한 자세한 설명

Y2J
Y2J원래의
2017-05-13 10:40:541501검색

이 글에서는 마이바티스 튜토리얼의 쿼리 캐시(1단계 캐시, 2단계 캐시, 통합 ehcache)를 주로 소개하는데, 관심 있는 친구들은 참고할 수 있습니다.

1 캐싱의 의미

사용자가 자주 쿼리하는 데이터를 캐시(메모리)에 넣어두세요. 사용자는 디스크(관계형 데이터베이스 데이터 파일)에서 데이터를 쿼리할 필요가 없고, 캐시 쿼리를 통해 쿼리 효율성을 높이고 동시성 시스템의 성능 문제를 해결합니다.

2개의 mybatis 지속성 레이어 캐시

mybatis는 1단계 캐시와 2단계 캐시를 제공합니다

mybatis 1차 수준 캐시는 SqlSession 수준입니다. sqlsession은 자체 1차 수준 캐시의 데이터에만 액세스할 수 있습니다. 매퍼 수준 캐시입니다. 매퍼 수준 캐시는 다른 sqlsession에서 공유할 수 있습니다.

3레벨 1 캐시

3.1 원칙

처음 sql 쿼리가 실행되면 sql 쿼리 결과가 sqlsession의 1차 캐시에 기록됩니다. 캐시에 사용되는 데이터 구조는 맵

key: hashcode+ sql+sql 입력 매개변수 + 출력 매개변수(sql의 고유 식별자)

value: 사용자 정보

동일한 sqlsession이 동일한 sql을 발행하는 경우 다시 말하면 캐시에서 가져옵니다. 데이터베이스를 사용하지 마세요. 두 번 사이에 커밋 작업(수정, 추가, 삭제)이 있으면 이 sqlsession의 1단계 캐시 영역이 지워지고 다음 번에는 캐시가 쿼리되지 않으므로 이를 수행해야 합니다. 데이터베이스에서 캐시로 다시 쿼리됩니다.

각 쿼리는 먼저 캐시를 쿼리합니다.


쿼리가 캐시에서 발견되면 캐시 데이터직접 반품하세요.

캐시에서 쿼리를 찾을 수 없는 경우 데이터베이스에서 쿼리합니다.

3.2 레벨 1 캐시 구성

Mybatis는 기본적으로 1단계 캐시를 지원하며 구성이 필요하지 않습니다.

참고: 매퍼 에이전트 개발은 mybatis와 spring 통합 후에 수행됩니다. Mybatis와 spring은 통합되어 매퍼 에이전트 개체를 생성합니다. 그리고 매퍼 템플릿에 따라 sqlsession을 균일하게 닫습니다.

3.3 레벨 1 캐시 테스트


//一级缓存 
  @Test 
  public void testCache1() throws Exception { 
 
    SqlSession sqlSession = sqlSessionFactory.openSession(); 
    UserMapper userMapper = sqlSession.getMapper(UserMapper.class); 
     
    //第一次查询用户id为1的用户 
    User user = userMapper.findUserById(1); 
    System.out.println(user); 
     
    //中间修改用户要清空缓存,目的防止查询出脏数据 
    /*user.setUsername("测试用户2"); 
    userMapper.updateUser(user); 
    sqlSession.commit();*/ 
     
    //第二次查询用户id为1的用户 
    User user2 = userMapper.findUserById(1); 
    System.out.println(user2); 
     
    sqlSession.close(); 
     
 
  }

4 레벨 2 캐시

4.1 원리

2차 레벨 캐시의 범위는 매퍼 레벨(매퍼 이름은 동일한

Space)를 사용하여 매퍼는 네임스페이스 단위로 캐시 데이터 구조를 생성하며 그 구조는 map입니다.

쿼리할 때마다 먼저 2차 캐시가 활성화되어 있는지 확인하세요. 2차 캐시의 데이터 구조에서 캐시된 데이터를 가져올 수 있도록 활성화되어 있으면


2차 캐시에서 얻지 못한 경우 1차 캐시에서 검색하고, 1차 캐시에서 찾지 못한 경우에는 질의한다. 데이터 베이스.


4.2 mybatis 2단계 캐시 구성

코어

구성 파일 SqlMapConfig에

<setting name="cacheEnabled" value="true"/>

Mapper 매핑 파일에 줄을 추가하려면: 8b0f252edde2ed6702a65a8dd34c5e13 은닉처.

4.3 쿼리 결과 매핑의 Pojo 직렬화


Mybatis 2차 캐시는 쿼리 결과에 대해 Java.io.serialized

인터페이스를 구현해야 합니다. 매핑 pojo

, 구현되지 않은 경우 예외가 발생합니다.
org.apache.ibatis.cache.CacheException: 개체 직렬화 오류 원인: java.io.NotSerializedException: com .sihai.mybatis.po.User


두 번째 수준 캐시는 메모리 데이터를 디스크에 쓸 수 있으므로 객체의 직렬화 및 역직렬화가 있으므로 java.io.serialized 인터페이스를 구현해야 합니다.


결과 매핑의 pojo에도 pojo가 포함되어 있는 경우 java.io.serialized 인터페이스를 구현해야 합니다.

4.4 二级缓存禁用

对于变化频率较高的sql,需要禁用二级缓存:

在statement中设置useCache=false可以禁用当前select语句的二级缓存,即每次查询都会发出sql去查询,默认情况是true,即该sql使用二级缓存。


<select id="findOrderListResultMap" resultMap="ordersUserMap" useCache="false">

4.5 刷新缓存

如果sqlsession操作commit操作,对二级缓存进行刷新(全局清空)。

设置statement的flushCache是否刷新缓存,默认值是true。

4.6 测试代码


//二级缓存的测试 
  @Test 
  public 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 user = userMapper1.findUserById(1); 
    System.out.println(user); 
    sqlSession1.close(); 
     
    //中间修改用户要清空缓存,目的防止查询出脏数据 
    /*user.setUsername("测试用户2"); 
    userMapper3.updateUser(user); 
    sqlSession3.commit(); 
    sqlSession3.close();*/ 
     
     
    //第二次查询用户id为1的用户 
    User user2 = userMapper2.findUserById(1); 
    System.out.println(user2); 
     
    sqlSession2.close(); 
     
 
  }

4.7 mybatis的cache参数

mybatis的cache参数只适用于mybatis维护缓存。

flushInterval(刷新间隔)可以被设置为任意的正整数,而且它们代表一个合理的毫秒形式的时间段。默认情况是不设置,也就是没有刷新间隔,缓存仅仅调用语句时刷新。

size(引用数目)可以被设置为任意正整数,要记住你缓存的对象数目和你运行环境的可用内存资源数目。默认值是1024。

readOnly(只读)属性可以被设置为true或false。只读的缓存会给所有调用者返回缓存对象的相同实例。因此这些对象不能被修改。这提供了很重要的性能优势。可读写的缓存会返回缓存对象的拷贝(通过序列化)。这会慢一些,但是安全,因此默认是false。

如下例子:


<cache eviction="FIFO" flushInterval="60000" size="512" readOnly="true"/>

这个更高级的配置创建了一个 FIFO 缓存,并每隔 60 秒刷新,存数结果对象或列表的 512 个引用,而且返回的对象被认为是只读的,因此在不同线程中的调用者之间修改它们会导致冲突。可用的收回策略有, 默认的是 LRU:

1. LRU – 最近最少使用的:移除最长时间不被使用的对象。

2. FIFO – 先进先出:按对象进入缓存的顺序来移除它们。

3. SOFT – 软引用:移除基于垃圾回收器状态和软引用规则的对象。

4. WEAK – 弱引用:更积极地移除基于垃圾收集器状态和弱引用规则的对象。

5 mybatis和ehcache缓存框架整合

mybatis二级缓存通过ehcache维护缓存数据。

5.1 分布缓存

将缓存数据数据进行分布式管理。

5.2 mybatis和ehcache思路

通过mybatis和ehcache框架进行整合,就可以把缓存数据的管理托管给ehcache。

在mybatis中提供一个cache接口,只要实现cache接口就可以把缓存数据灵活的管理起来。

mybatis中默认实现:

5.3 下载和ehcache整合的jar包

 

ehcache对cache接口的实现类:

5.4 配置ehcache.xml


<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
  xsi:noNamespaceSchemaLocation="../config/ehcache.xsd"> 
  <!--diskStore:缓存数据持久化的目录 地址 --> 
  <diskStore path="F:\develop\ehcache" /> 
  <defaultCache  
    maxElementsInMemory="1000"  
    maxElementsOnDisk="10000000" 
    eternal="false"  
    overflowToDisk="false"  
    diskPersistent="true" 
    timeToIdleSeconds="120" 
    timeToLiveSeconds="120"  
    diskExpiryThreadIntervalSeconds="120" 
    memoryStoreEvictionPolicy="LRU"> 
  </defaultCache> 
</ehcache>

5.5 整合测试

在mapper.xml添加ehcache配置:


<!-- 开启二级缓存 --> 
  <!-- 单位:毫秒 --> 
  <cache type="org.mybatis.caches.ehcache.EhcacheCache"> 
    <property name="timeToIdleSeconds" value="12000"/> 
    <property name="timeToLiveSeconds" value="3600"/> 
    <!-- 同ehcache参数maxElementsInMemory --> 
    <property name="maxEntriesLocalHeap" value="1000"/> 
    <!-- 同ehcache参数maxElementsOnDisk --> 
    <property name="maxEntriesLocalDisk" value="10000000"/> 
    <property name="memoryStoreEvictionPolicy" value="LRU"/> 
  </cache>

6 二级缓存的应用场景

对查询频率高,变化频率低的数据建议使用二级缓存。

对于访问多的查询请求且用户对查询结果实时性要求不高,此时可采用mybatis二级缓存技术降低数据库访问量,提高访问速度,业务场景比如:耗时较高的统计分析sql、电话账单查询sql等。

实现方法如下:通过设置刷新间隔时间,由mybatis每隔一段时间自动清空缓存,根据数据变化频率设置缓存刷新间隔flushInterval,比如设置为30分钟、60分钟、24小时等,根据需求而定。

7 mybatis局限性

Mybatis 2차 캐시는 상품 정보 캐싱 요구사항과 같은 세분화된 데이터 레벨 캐싱에는 적합하지 않습니다. 상품 정보 조회 방문 횟수가 많기 때문에 사용자는 매회 최신 상품 정보를 조회해야 합니다. 이때, 마이바티스의 2차 캐시를 사용하면 제품이 변경될 때 다른 제품의 정보를 갱신하지 않고 해당 제품의 캐시 정보만 갱신하는 기능을 구현할 수 없습니다. mybaits의 2차 캐시 영역은 매퍼 단위로 나누어져 있기 때문에, 상품 정보가 변경되면 모든 상품 정보 중 캐시된 데이터가 모두 삭제됩니다. 이러한 문제를 해결하려면 비즈니스 계층의 요구 사항에 따라 데이터를 대상으로 캐싱해야 합니다.

【관련 추천】

1. 특별 추천: "php Programmer Toolbox" V0.1 버전 다운로드

2. Java 무료 동영상 튜토리얼

3. Java 주석 종합 분석

위 내용은 mybatis의 캐시 예제에 대한 자세한 설명의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.