【MyBatis框架】查询缓存-二级缓存-整合ehcache

简介:
mybatis整合ehcache

ehcache是一个分布式缓存框架。

1.分布缓存
我们系统为了提高系统并发,性能、一般对系统进行分布式部署(集群部署方式)

如图



不使用分布缓存,缓存的数据在各各服务单独存储,不方便系统开发。所以要使用分布式缓存对缓存数据进行集中管理。

mybatis无法实现分布式缓存,需要和其它分布式缓存框架进行整合。

2.整合方法(掌握)

mybatis提供了一个cache接口,如果要实现自己的缓存逻辑,实现cache接口开发即可。

mybatis和ehcache整合,mybatis和ehcache整合包中提供了一个cache接口的实现类。

mybatis默认实现cache类(接口)是:
此接口在MyBatis-3.2.7.jar下的org.apache.ibatis.cache包下的Cache.class
package org.apache.ibatis.cache;

import java.util.concurrent.locks.ReadWriteLock;

public interface Cache {
  
	//缓存在唯一标示
	String getId();
  
	//存入到缓存中
	void putObject(Object key, Object value);
 
	//根据key取出缓存
 	Object getObject(Object key);

	//移除key 
 	Object removeObject(Object key);

  	void clear();

 	int getSize();
  
	ReadWriteLock getReadWriteLock();
}

MyBatis默认实现支持的cache类是:
package org.apache.ibatis.cache.impl;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.ReadWriteLock;
import org.apache.ibatis.cache.Cache;
import org.apache.ibatis.cache.CacheException;

public class PerpetualCache implements Cache {

private String id;
  
private Map<Object, Object> cache = new HashMap<Object, Object>();

public PerpetualCache(String id) 
{
   
this.id = id;
  
}

public String getId() {
    
return id;
}
  
public int getSize() {
    
return cache.size();
  
}

public void putObject(Object key, Object value) {
   
 cache.put(key, value);
  
}

public Object getObject(Object key) {
    
return cache.get(key);
  
}

public Object removeObject(Object key) {
    
return cache.remove(key);
  
}

public void clear() {
    
cache.clear();
  
}

public ReadWriteLock getReadWriteLock() {
    
return null;
 
 }

 
 public boolean equals(Object o) {
    
if (getId() == null) 
throw new CacheException("Cache instances require an ID.");
    
if (this == o) return true;
    
if (!(o instanceof Cache)) return false;
    
Cache otherCache = (Cache) o;
    
return getId().equals(otherCache.getId());
  
}

public int hashCode() {
    
if (getId() == null) 
throw new CacheException("Cache instances require an ID.");
    
return getId().hashCode();
  }

}
可以根据它来写新的实现类

3.加入ehcache包
ehcache-core-2.6.5.jar和mybatis-ehcache-1.0.2.jar
一个是ehcache自己的,一个是和mybatis的整合包

4.整合ehcache
配置mapper中cache中的type为ehcache对cache接口的实现类型。
我们在mybatis-ehcache-1.0.2.jar下找到org.mybatis.caches.ehcache包下有EhcacheCache.class类,这个就是ehcache整合mybatis的Cache接口的实现
UserMapper.xml:
<mapper namespace="cn.edu.hpu.mybatis.mapper.UserMapper">

	<!-- 开启本Mapper的namespace下的二级缓存 
	type:执行cache接口实现类的类型,mybatis默认使用PerpatualCache,
	要和ehcache整合,需要配置type为ehcache实现cache接口的类型-->
    <cache type="org.mybatis.caches.ehcache.EhcacheCache"/>
	......
</mapper>

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>

测试:
//测试二级缓存
	@Test
	public void testCache2() throws Exception{
		SqlSession sqlSession1 = sqlSessionFactory.openSession();
		SqlSession sqlSession2 = sqlSessionFactory.openSession();
		SqlSession sqlSession3 = sqlSessionFactory.openSession();
		
		UserMapper userMapper1 = sqlSession1.getMapper(UserMapper.class);//创建代理对象
		//下边查询使用一个SqlSession
		//第一次发起请求,查询id为1的用户
		User user1 = userMapper1.findUserById(1);
		System.out.println(user1.getUsername());
		//不关闭SqlSession无法写进二级缓存区域中
		sqlSession1.close();
		
		UserMapper userMapper2 = sqlSession2.getMapper(UserMapper.class);//创建代理对象
		//第二次发起请求,查询id为1的用户
		User user2 = userMapper2.findUserById(1);
		System.out.println(user2.getUsername());
		sqlSession2.close();
}
结果和输出日志:
DEBUG [main] - Cache Hit Ratio [cn.edu.hpu.mybatis.mapper.UserMapper]: 0.0
DEBUG [main] - Opening JDBC Connection
DEBUG [main] - Created connection 4554017.
DEBUG [main] - Setting autocommit to false on JDBC Connection [com.mysql.jdbc.Connection@457d21]
DEBUG [main] - ==>  Preparing: SELECT * FROM USER WHERE id=? 
DEBUG [main] - ==> Parameters: 1(Integer)
DEBUG [main] - <==      Total: 1
张明明
DEBUG [main] - Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.Connection@457d21]
DEBUG [main] - Closing JDBC Connection [com.mysql.jdbc.Connection@457d21]
DEBUG [main] - Returned connection 4554017 to pool.
DEBUG [main] - Cache Hit Ratio [cn.edu.hpu.mybatis.mapper.UserMapper]: 0.5
张明明

整合ehcache成功!
6.二级应用场景
对于访问多的查询请求且用户对查询结果实时性要求不高,此时可采用mybatis二级缓存技术降低数据库访问量,提高访问速度,业务场景比如:耗时较高的统计分析sql、电话账单查询sql等。
实现方法如下:通过设置刷新间隔时间,由mybatis每隔一段时间自动清空缓存,根据数据变化频率设置缓存刷新间隔flushInterval,比如设置为30分钟、60分钟、24小时等,根据需求而定。

7.二级缓存局限性
mybatis二级缓存对细粒度的数据级别的缓存实现不好,比如如下需求:对商品信息进行缓存,由于商品信息查询访问量大,但是要求用户每次都能查询最新的商品信息,此时如果使用mybatis的二级缓存就无法实现当一个商品变化时只刷新该商品的缓存信息而不刷新其它商品的信息,因为mybaits的二级缓存区域以mapper为单位划分,当一个商品信息变化会将所有商品信息的缓存数据全部清空。解决此类问题需要在业务层根据需求对数据有针对性缓存。
转载请注明出处:http://blog.csdn.net/acmman/article/details/46793355
相关文章
|
2月前
|
缓存 Java 数据库连接
mybatis复习05,mybatis的缓存机制(一级缓存和二级缓存及第三方缓存)
文章介绍了MyBatis的缓存机制,包括一级缓存和二级缓存的配置和使用,以及如何整合第三方缓存EHCache。详细解释了一级缓存的生命周期、二级缓存的开启条件和配置属性,以及如何通过ehcache.xml配置文件和logback.xml日志配置文件来实现EHCache的整合。
mybatis复习05,mybatis的缓存机制(一级缓存和二级缓存及第三方缓存)
|
2月前
|
Java 数据库连接 数据库
mybatis查询数据,返回的对象少了一个字段
mybatis查询数据,返回的对象少了一个字段
176 8
|
12天前
|
SQL Java 数据库连接
持久层框架MyBatisPlus
持久层框架MyBatisPlus
31 1
持久层框架MyBatisPlus
|
13天前
|
SQL 缓存 Java
【详细实用のMyBatis教程】获取参数值和结果的各种情况、自定义映射、动态SQL、多级缓存、逆向工程、分页插件
本文详细介绍了MyBatis的各种常见用法MyBatis多级缓存、逆向工程、分页插件 包括获取参数值和结果的各种情况、自定义映射resultMap、动态SQL
【详细实用のMyBatis教程】获取参数值和结果的各种情况、自定义映射、动态SQL、多级缓存、逆向工程、分页插件
|
19天前
|
SQL 安全 Java
MyBatis-Plus条件构造器:构建安全、高效的数据库查询
MyBatis-Plus 提供了一套强大的条件构造器(Wrapper),用于构建复杂的数据库查询条件。Wrapper 类允许开发者以链式调用的方式构造查询条件,无需编写繁琐的 SQL 语句,从而提高开发效率并减少 SQL 注入的风险。
13 1
MyBatis-Plus条件构造器:构建安全、高效的数据库查询
|
14天前
|
SQL 缓存 Java
MyBatis如何关闭一级缓存(分注解和xml两种方式)
MyBatis如何关闭一级缓存(分注解和xml两种方式)
43 5
|
24天前
|
SQL Java 数据库连接
mybatis如何仅仅查询某个表的几个字段
【10月更文挑战第19天】mybatis如何仅仅查询某个表的几个字段
27 1
|
2月前
|
缓存 Java 开发工具
Spring是如何解决循环依赖的?从底层源码入手,详细解读Spring框架的三级缓存
三级缓存是Spring框架里,一个经典的技术点,它很好地解决了循环依赖的问题,也是很多面试中会被问到的问题,本文从源码入手,详细剖析Spring三级缓存的来龙去脉。
189 24
Spring是如何解决循环依赖的?从底层源码入手,详细解读Spring框架的三级缓存
|
29天前
|
缓存 Java 数据库连接
使用MyBatis缓存的简单案例
MyBatis 是一种流行的持久层框架,支持自定义 SQL 执行、映射及复杂查询。本文介绍了如何在 Spring Boot 项目中集成 MyBatis 并实现一级和二级缓存,以提高查询性能,减少数据库访问。通过具体的电商系统案例,详细讲解了项目搭建、缓存配置、实体类创建、Mapper 编写、Service 层实现及缓存测试等步骤。
|
1月前
|
存储 缓存 索引
从底层数据结构和CPU缓存两方面剖析LinkedList的查询效率为什么比ArrayList低
本文详细对比了ArrayList和LinkedList的查询效率,从底层数据结构和CPU缓存两个方面进行分析。ArrayList基于动态数组,支持随机访问,查询时间复杂度为O(1),且CPU缓存对其友好;而LinkedList基于双向链表,需要逐个节点遍历,查询时间复杂度为O(n),且CPU缓存对其帮助不大。文章还探讨了CPU缓存对数组增删操作的影响,指出缓存主要作用于读取而非修改。通过这些分析,加深了对这两种数据结构的理解。
35 2