1. 作用
MyBatis的一级缓存是指在同一个SqlSession中,多次执行同一个查询语句,第一次执行后查询结果会被缓存到内存中,后续执行同一个查询语句时,会直接从缓存中获取结果,而不会再次向数据库发送查询请求。
一级缓存是MyBatis默认开启的,它的实现方式是将缓存存储在SqlSession对象中。当SqlSession执行查询操作时,查询结果会被存储在一个HashMap对象中,该HashMap对象的作用域是当前SqlSession对象。
一级缓存的生命周期与SqlSession对象的生命周期一样长,当SqlSession对象被关闭或提交事务时,一级缓存也会被清空。
一级缓存是针对同一个SqlSession对象的,不同的SqlSession对象之间的缓存是互相独立的。
如果需要禁用一级缓存,可以在SqlSession执行查询操作前调用SqlSession的clearCache()方法清空缓存
2. 集成
2.1 导入需要的包
包括jedis,spring–data–redis以及jackson(在将对象序列化保存到redis中需要)
2.2 redis的属性配置文件
#访问地址
redis.host=192.168.62.147
#访问端口
redis.port=6379
#注意,如果没有password,此处不设置值,但这一项要保留
#redis.password=
#最大空闲数,数据库连接的最大空闲时间。超过空闲时间,数据库连接将被标记为不可用,然后被释放。设为0表示无限制。
redis.maxIdle=300
#连接池的最大数据库连接数。设为0表示无限制
redis.maxTotal=600
#最大建立连接等待时间。如果超过此时间将接到异常。设为-1表示无限制。
redis.maxWaitMillis=1000
#在borrow一个jedis实例时,是否提前进行alidate操作;如果为true,则得到的jedis实例均是可用的;
redis.testOnBorrow=true
2.3 spring 与redis集成配置
2.3.1 xml方式
xml配置文件放在resources目录下,已applicationContext–redis.xml命名
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context"
xmlns:cache="http://www.springframework.org/schema/cache"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache.xsd">
<!-- 连接池基本参数配置,类似数据库连接池 -->
<context:property-placeholder location="classpath:redis.properties"
ignore-unresolvable="true" />
<!-- redis连接池 -->
<bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig">
<property name="maxTotal" value="${redis.maxTotal}" />
<property name="maxIdle" value="${redis.maxIdle}" />
<property name="testOnBorrow" value="${redis.testOnBorrow}" />
</bean>
<!-- 连接池配置,类似数据库连接池 -->
<bean id="jedisConnectionFactory"
class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
<property name="hostName" value="${redis.host}"></property>
<property name="port" value="${redis.port}"></property>
<!-- <property name="password" value="${redis.pass}"></property> -->
<property name="poolConfig" ref="poolConfig"></property>
</bean>
<!--redis操作模版,使用该对象可以操作redis -->
<bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate" >
<property name="connectionFactory" ref="jedisConnectionFactory" />
<!--如果不配置Serializer,那么存储的时候缺省使用String,如果用User类型存储,那么会提示错误User can't cast to String!! -->
<property name="keySerializer" >
<bean class="org.springframework.data.redis.serializer.StringRedisSerializer" />
</property>
<property name="valueSerializer" >
<bean class="org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer" />
</property>
<property name="hashKeySerializer">
<bean class="org.springframework.data.redis.serializer.StringRedisSerializer"/>
</property>
<property name="hashValueSerializer">
<bean class="org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer"/>
</property>
<!--开启事务 -->
<property name="enableTransactionSupport" value="true"></property>
</bean >
<!-- 启用缓存 -->
<cache:annotation-driven cache-manager="cacheManager"/>
<!-- 声明reids缓存管理器 -->
<bean id="cacheManager" class="org.springframework.data.redis.cache.RedisCacheManager">
<constructor-arg index="0" ref="redisTemplate"></constructor-arg>
<!-- 用于指明过期时间 -->
<!--<property name="expires">
<map>
<entry key="students" value="#{60*2}"/>
</map>
</property>-->
</bean>
<bean id="customKeyGenerator"
class="com.zking.mybatisdemo.config.CustomKeyGenerator"/>
</beans>
2.3.2 程序方式配置
在源码中,可以新建一个config的包,用于放置配置相关的java文件。
@Configuration
@EnableCaching
public class CacheConfig {
private static final Logger log = LoggerFactory.getLogger(CacheConfig.class);
@Bean
public JedisConnectionFactory redisConnectionFactory() throws IOException {
ClassPathResource resource = new ClassPathResource("/redis.properties");
InputStream in = resource.getInputStream();
Properties prop = new Properties();
prop.load(in);
String host = prop.getProperty("redis.host");
Integer port = Integer.valueOf(prop.getProperty("redis.port"));
Integer maxIdle = Integer.valueOf(prop.getProperty("redis.maxIdle"));
Integer maxTotal = Integer.valueOf(prop.getProperty("redis.maxTotal"));
Integer maxWaitMillis = Integer.valueOf(prop.getProperty("redis.maxWaitMillis"));
boolean testOnBorrow = Boolean.valueOf(prop.getProperty("redis.testOnBorrow"));
JedisPoolConfig poolConfig = new JedisPoolConfig();
poolConfig.setMaxIdle(maxIdle);
poolConfig.setMaxTotal(maxTotal);
poolConfig.setMaxWaitMillis(maxWaitMillis);
poolConfig.setTestOnBorrow(testOnBorrow);
JedisConnectionFactory redisConnectionFactory = new JedisConnectionFactory();
redisConnectionFactory.setHostName(host);
redisConnectionFactory.setPort(port);
redisConnectionFactory.setPoolConfig(poolConfig);
return redisConnectionFactory;
}
@Bean
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory cf) {
RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(cf);
GenericJackson2JsonRedisSerializer genericJackson2JsonRedisSerializer = new GenericJackson2JsonRedisSerializer();
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setValueSerializer(genericJackson2JsonRedisSerializer);
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
redisTemplate.setHashValueSerializer(genericJackson2JsonRedisSerializer);
return redisTemplate;
}
@Bean
public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory factory) {
StringRedisTemplate stringRedisTemplate = new StringRedisTemplate();
stringRedisTemplate.setConnectionFactory(factory);
return stringRedisTemplate;
}
@Bean
public CacheManager cacheManager(RedisTemplate redisTemplate) {
RedisCacheManager cacheManager = new RedisCacheManager(redisTemplate);
//这里可以设置一个默认的过期时间
cacheManager.setDefaultExpiration(300);
return cacheManager;
}
@Bean
public KeyGenerator customKeyGenerator() {
return new KeyGenerator() {
@Override
public Object generate(Object o, Method method, Object... params) {
StringBuilder sb = new StringBuilder();
sb.append(o.getClass().getName());
sb.append(method.getName());
for (Object obj : params) {
sb.append(obj.toString());
}
return sb.toString();
}
};
}
}
3. 使用示例
- @Cacheable 主要针对方法配置,能够根据方法的请求参数对其结果进行缓存
- @CacheEvict 主要针对方法配置,能够根据一定的条件对缓存进行清空
- @CachePut 更新缓存(不会影响到方法的运行),这个注释可以确保方法被执行,同时方法的返回值也被记录到缓存中,实现缓存与数据库的同步更新。
- @Caching 重新组合要应用于方法的多个缓存操作
- @CacheConfig 设置类级别上共享的一些常见缓存设置
3.1 @Cacheable
3.1.1 通过指定的key,将查询结果缓存到redis中
@Service
public class StudentService implements IStudentService {
@Resource
private StudentMapper studentMapper;
@Cacheable(value = "students",key = "#student.toString()")
@Override
public List<Student> list(Student student) {
return studentMapper.list(student);
}
}
属性 | 描述 | 示例 |
---|---|---|
methodName | 当前方法名 | #root.methodName |
method | 当前方法 | #root.method.name |
target | 当前被调用的对象 | #root.target |
targetClass | 当前被调用的对象的class | #root.targetClass |
args | 当前方法参数组成的数组 | #root.args[0] |
result | 获取方法的返回值 | #result.id 表示获取返回值中的id属性的值 |
3.1.2 配置key的生成策略
public class CustomKeyGenerator implements KeyGenerator {
@Override
public Object generate(Object target, Method method, Object... params) {
StringBuilder sb = new StringBuilder();
sb.append(target.getClass().getName());
sb.append(method.getName());
for (Object obj : params) {
sb.append(obj.toString());
}
return sb.toString();
}
}
<!-- 启用注解式缓存 -->
<cache:annotation-driven cache-manager="cacheManager" key-generator="customKeyGenerator"/>
<!--自定义key生成器-->
<bean id="customKeyGenerator" class="com.zking.mybatisdemo.config.CustomKeyGenerator"/>
@Configuration
@EnableCaching
public class CacheConfig extends CachingConfigurerSupport {
private static final Logger log = LoggerFactory.getLogger(CacheConfig.class);
......
@Bean
public CacheManager cacheManager(RedisTemplate redisTemplate) {
RedisCacheManager cacheManager = new RedisCacheManager(redisTemplate);
//这里可以设置一个默认的过期时间
cacheManager.setDefaultExpiration(300);
return cacheManager;
}
@Bean(name="customKeyGenerator")
public KeyGenerator customKeyGenerator() {
return new CustomKeyGenerator();
}
//配置自定义key生成器
@Override
public KeyGenerator keyGenerator() {
return new CustomKeyGenerator();
}
}
配置默认的生成策略后,如果没有指定key,则使用默认的生成策略, 如:
@Cacheable(value = "students")
@Override
public List<Student> list(Student student) {
return studentMapper.list(student);
}
3) 除默认key生成策略外,还可以指定key,或指定生成策略,如果一下示例:
@Cacheable(value = "students", key = "'sname:' + #student.sname")
@Override
public List<Student> list(Student student) {
return studentMapper.list(student);
}
@Override
@Cacheable(value="student",keyGenerator = "customKeyGenerator")
public Student load(String sid) {
return studentMapper.load(Integer.valueOf(sid));
}
3.1.3 condition
只对学生名称以“李”字开发的的查询执行缓存,否则不进行缓存, 代码如下:
@Cacheable(value = "students", key = "'sname:' + #student.sname", condition = "#student.sname.equals('李')")
@Override
public List<Student> list(Student student) {
return studentMapper.list(student);
}
3.2 @CacheEvict
示例:
@Override
@Cacheable(value="student", key="#sid.toString()")
public Student load(Integer sid) {
return studentMapper.load(sid);
}
@CacheEvict(value="student", key="T(Integer).toString(#student.sid)")
//@CacheEvict(value="student", key="#student.sid + ''")
@Override
public void update(Student student) {
studentMapper.update(student);
}
@Test
public void load() {
Student student = studentService.load(197);
System.out.println(student);
}
@Test
public void update() {
Student student = new Student();
student.setSid(197);
student.setSname("曹雪学");
student.setAge(56);
student.setRemark("测试");
studentService.update(student);
}
先运行load测试, 会将sid为197的学生信息缓存,然后再运行update,会将sid为197的学习信息从缓存中删除。
@CacheEvict(cacheNames="books", allEntries=true)
@Override
public void update(Student student) {
studentMapper.update(student);
}
清除操作默认是在对应方法成功执行之后触发的,即方法如果因为抛出异常而未能成功返回时也不会触发清除操作。使用beforeInvocation可以改变触发清除操作的时间,当我们指定该属性值为true时,Spring会在调用该方法之前清除缓存中的指定元素
示例:
@CacheEvict(value="users", beforeInvocation=true)
3.3 @CachePut
对于使用@Cacheable标注的方法,Spring在每次执行前都会检查Cache中是否存在相同key的缓存元素,如果存在就不再执行该方法,而是直接从缓存中获取结果进行返回,否则才会执行并将返回结果存入指定的缓存中。@CachePut也可以声明一个方法支持缓存功能。与@Cacheable不同的是使用@CachePut标注的方法在执行前不会去检查缓存中是否存在之前执行过的结果,而是每次都会执行该方法,并将执行结果以键值对的形式存入指定的缓存中。
示例:
@Override
//@Cacheable(value="student", key="#sid.toString()")
@CachePut(value = "student", key="#sid.toString()")
public Student load(Integer sid) {
return studentMapper.load(sid);
}
注意: @CachePut 与 @Cacheable 之间的差别,@CachePut不会去检查缓存中是否有值, 每次都会通过获取获取数据填充到缓存中去。
3.4 @Caching
@Caching注解可以作为一个容器注解,用于组合多个缓存注解,实现多个缓存操作在一个方法中的统一配置
@Caching注解的作用是将多个缓存注解组合在一起,作为一个缓存操作的配置信息。例如,一个方法需要在缓存中查询一个对象,如果找到了就返回,否则从数据库中查询并将结果存储到缓存中。这个操作可以通过@Caching注解来实现,如下所示:
示例代码如下:
@Caching(
cacheable = {
@Cacheable(value = "myCache", key = "#id")
},
put = {
@CachePut(value = "myCache", key = "#id"),
@CachePut(value = "myOtherCache", key = "#result.name")
}
)
public MyObject findMyObjectById(String id) {
// ...
}
在上面的示例中,@Caching注解包含了两个缓存操作:@Cacheable和@CachePut。@Cacheable注解用于从缓存中查询MyObject对象,@CachePut注解用于将MyObject对象存储到缓存中。同时,@CachePut注解还配置了将MyObject对象的name属性作为key存储到另一个缓存中(myOtherCache)
3.5 @CacheConfig
缓存提供了许多的注解选项,但是有一些公用的操作,我们可以使用@CacheConfig在类上进行全局设置。
@CacheConfig(keyGenerator = "customKeyGenerator")
public class StudentService implements IStudentService {
@Cacheable(value = "students")
@Override
public List<Student> list(Student student) {
return studentMapper.list(student);
}
....
}
原文地址:https://blog.csdn.net/qq_73126462/article/details/134784406
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.7code.cn/show_38700.html
如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱:suwngjj01@126.com进行投诉反馈,一经查实,立即删除!