首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >1 Springboot中使用redis,自动缓存、更新、删除

1 Springboot中使用redis,自动缓存、更新、删除

作者头像
天涯泪小武
发布于 2019-01-17 03:07:26
发布于 2019-01-17 03:07:26
4.5K0
举报
文章被收录于专栏:SpringCloud专栏SpringCloud专栏

第一篇记录一下在springboot中,redis的基础用法,自动缓存新增的数据,自动修改及删除。

在本机安装好mysql和redis。新建一个springboot的web项目,在新建项目时勾选redis,mysql。

pom文件如下:

代码语言:javascript
AI代码解释
复制
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>

	<groupId>com.tianyalei</groupId>
	<artifactId>demo0</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>jar</packaging>

	<name>demo0</name>
	<description>Demo project for Spring Boot</description>

	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>1.5.2.RELEASE</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
		<java.version>1.8</java.version>
	</properties>

	<dependencies>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-jpa</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-redis</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
			<groupId>com.alibaba</groupId>
			<artifactId>druid</artifactId>
			<version>1.0.18</version>
		</dependency>
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<scope>runtime</scope>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>


</project>

数据库连接池用的druid,里面使用了spring-boot-starter-data-redis,有这一个依赖就够了,系统就能识别并应用redis了。dao工具用的jpa,默认集成了hibernate。

下面配置一下application.yml。如下:

代码语言:javascript
AI代码解释
复制
spring:
  jpa:
    database: mysql
    show-sql: true
    hibernate:
      ddl-auto: update
  datasource:
      type: com.alibaba.druid.pool.DruidDataSource
      driver-class-name: com.mysql.jdbc.Driver
      url: jdbc:mysql://localhost:3306/tx2
      username: root
      password:

配置一下show-sql为true,目的是看看查表时的缓存效果。至于redis的ip,端口什么的都不用配,系统有个默认值,等会看看就知道了。 

创建个java bean。

代码语言:javascript
AI代码解释
复制
package com.tianyalei.domain;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import java.io.Serializable;

/**
 * Created by wuwf on 17/4/21.
 */
@Entity
public class Post implements Serializable{
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Integer id;

    private String content;

    private Integer weight;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }

    public Integer getWeight() {
        return weight;
    }

    public void setWeight(Integer weight) {
        this.weight = weight;
    }
}

创建个repository

代码语言:javascript
AI代码解释
复制
package com.tianyalei.repository;

import com.tianyalei.domain.Post;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.repository.PagingAndSortingRepository;
import org.springframework.transaction.annotation.Transactional;

/**
 * Created by wuwf on 17/4/20.
 */
@CacheConfig(cacheNames = "post")
public interface PostRepository extends PagingAndSortingRepository<Post, Integer> {
    @Cacheable(key = "#p0")
    Post findById(int id);

    /**
     * 新增或修改时
     */
    @CachePut(key = "#p0.id")
    @Override
    Post save(Post post);

    @Transactional
    @Modifying
    int deleteById(int id);
}

这个里面有个CacheConfig,配置了cacheNames。

我在findById方法时加了个@Cacheable(key= "#p0"),#p0代表第一个参数,也就是id。这句话加上之后,当你在调用findById时,就会先从redis的post缓存对象里去查询key等于传过来的id的值。如果没有,就去查表。

在save方法上加了个CachePut,代表往缓存里添加值,key为参数post的id属性,这样当我们save一个Post对象时,redis就会新增一个以id为key的Post对象;如果是update操作,那同样,redis会覆盖id相同的Post对象的值,也完成一次更新。更多标签,请看http://docs.spring.io/spring/docs/current/spring-framework-reference/html/cache.html#cache-spel-context

这样,在对post的新增和修改时都会自动缓存到redis里。

下面来验证一下。

加个service

代码语言:javascript
AI代码解释
复制
package com.tianyalei.service;

import com.tianyalei.domain.Post;
import com.tianyalei.repository.PostRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;


/**
 * Created by wuwf on 17/4/20.
 */
@Service
public class PostService {
    @Autowired
    private PostRepository postRepository;

    public Post findById(int id) {
        return postRepository.findById(id);
    }

    public Post save(Post post) {
        return postRepository.save(post);
    }

    public int delete(int id) {
        return postRepository.deleteById(id);
    }
}

来个controller

代码语言:javascript
AI代码解释
复制
package com.tianyalei.controller;

import com.tianyalei.domain.Post;
import com.tianyalei.service.PostService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;


/**
 * Created by wuwf on 17/4/20.
 */
@RestController
public class PostController {
    @Autowired
    private PostService postService;

    @RequestMapping("/query/{id}")
    public Object query(@PathVariable int id) {
        return postService.findById(id);
    }

    @RequestMapping("/save")
    public Object save(@ModelAttribute Post post) {
        return postService.save(post);
    }

    @RequestMapping("/delete/{id}")
    public Object delete(@PathVariable int id) {
        return postService.delete(id);
    }

    @RequestMapping("/queryPage")
    public Object query(String name, int pageNum, int count) {
        //根据weight倒序分页查询
//        Pageable pageable = new PageRequest(pageNum, count, Sort.Direction.DESC, "weight");
//        return userRepository.findByName(name, pageable);
        return null;
    }
}

然后启动Application,在启动之前需要加上@EnableCaching注解,缓存才能正常工作。

代码语言:javascript
AI代码解释
复制
package com.tianyalei;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;

@SpringBootApplication
@EnableCaching
public class Demo0Application {

	public static void main(String[] args) {
		SpringApplication.run(Demo0Application.class, args);
	}
}

启动后访问 http://localhost:8080/save?content=1&weight=1

这样就添加了一条记录,控制台有一个insert语句。

然后访问查询,http://localhost:8080/query/1

会发现查询到了id为1的这条记录,并且控制台没有走select查询语句,也就是根本没访问数据库,直接从redis缓存拿的值。

下面做一个更新操作,看看是否会同步到redis里。http://localhost:8080/save?content=1&weight=2&id=1

把weight改为2,访问地址看看结果。

控制台打印了两条语句

Hibernate: select post0_.id as id1_0_0_, post0_.content as content2_0_0_, post0_.weight as weight3_0_0_ from post post0_ where post0_.id=? Hibernate: update post set content=?, weight=? where id=?

说明数据已经被更新了。然后再查询http://localhost:8080/query/1

发现查到的数据已经改变,并且控制台没有走select语句,说明在update时,redis已经更新了。

下面做删除操作,可以直接在数据库里删这条记录,或者通过浏览器访问来删除。http://localhost:8080/delete/1

控制台走了删除delete语句。再访问查询地址。发现依旧能查到这条记录,也就是db的删除成功了,但redis并没有删除。

那么怎么在db删除时,也删除redis的相关记录呢?

用CacheEvict

代码语言:javascript
AI代码解释
复制
@CacheConfig(cacheNames = "post")
public interface PostRepository extends PagingAndSortingRepository<Post, Integer> {
    @Cacheable(key = "#p0")
    Post findById(int id);

    /**
     * 新增或修改时
     */
    @CachePut(key = "#p0.id")
    @Override
    Post save(Post post);

    @Transactional
    @Modifying
    @CacheEvict(key = "#p0")
    int deleteById(int id);
}

加上这个标签后,再走deleteById方法时,就会删除掉key为id的redis记录了。可以重启试试,访问http://localhost:8080/delete/1

然后再查询就会发现id为1的值已经查不到了。

这样我们就完成了一个最简单的整合redis的demo。包括了对单个对象的增删改查的缓存。

那么下面来讲几个疑问:

1.为什么不用配置redis的地址,port,密码什么的?

上面的那些默认的对redis的操作,来源于Springboot里整合的RedisTemplate,template里会默认使用一个JedisConnectionFactory来做默认的连接属性配置。

这里面已经对jedis的连接地址和jedisPool做了初始化操作了,都是默认值。系统就会使用这些默认值来操作redis。

后面我们会对Connection进行自定义,设置value的序列化方式,还有修改连接地址,那时就会使用自定义的配置了。

2.能否用上面的方法来存储集合?譬如所有的Post集合,当新增时集合也随之改变?

不行的,假如给List<Post> findAll做了个缓存,那下次查询时确实不用查表了,但是当你新增、修改、删除任何一个对象时,这个缓存的集合都是不变的。

除非你在所有的能修改对象的地方,都加上CacheEvict,key为集合的key,这样任何修改,都是删除整个集合对象的缓存,下次再查时才能缓存起来。而大部分时候,集合对象都是在不停变化的,除了一些不变的如城市列表之类的,其他的都不适合用这种缓存方式。会导致频繁创建大对象,而且大部分时候也不需要查整个集合,而是分页。

3.怎么用redis来做集合查询,分页查询,甚至于条件分页查询?

这个也是问题2的延续,后面一篇会讲。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2017年04月21日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
解释SpringBoot之Ehcache 2.x缓存
[wp_editor_md_a364d1423e3bdfc4066b7266a02a2393.jpg]
mySoul
2020/06/20
4300
4 Springboot中使用redis存储集合数据,并模拟条件查询、分页读取
前面几篇讲了使用redis存储单个对象,自动缓存、更新、删除的做法,在实际项目中,更常用的是分页查询集合数据,条件查询(譬如按照添加时间倒序排列)。
天涯泪小武
2019/01/17
8.7K0
SpringBoot系列-- 集成 Redis 缓存(实战)
通过控制台输出信息我们可以知道,这次执行了数据库查询,并开启了Redis缓存查询结果。接下来我们再次查询user表中id=24的数据,观察控制台,如下:
田维常
2020/02/13
2.1K0
SpringBoot系列-- 集成 Redis 缓存(实战)
2 Springboot中使用redis,配置redis的key value生成策略
上一篇里讲过了redis在spring boot中的简单使用,对于单个对象的增删改查的默认操作。
天涯泪小武
2019/01/17
4.1K2
有Redis为什么还要本地缓存?谈谈你对本地缓存的理解?
本地缓存是将数据存储在应用程序所在的本地内存中的缓存方式。既然,已经有了 Redis 可以实现分布式缓存了,为什么还需要本地缓存呢?接下来,我们一起来看。
磊哥
2024/11/01
3200
1 秒杀系统模拟基础实现,使用DB实现
业务隔离:将秒杀业务独立出来,尽量不与其他业务关联,以减少对其他业务的依赖性。譬如秒杀业务只保留用户id,商品id,数量等重要属性,通过中间件发送给业务系统,完成后续的处理。
天涯泪小武
2019/01/17
5360
(11)SpringBoot整合EhCache做缓存
EhCache 简介:EhCache 是一个纯Java的进程内缓存框架,是Hibernate中默认的CacheProvider;其缓存的数据可以存放在内存里面,也可以存放在硬盘上;其核心是CacheManager,一切Ehcache的应用都是从CacheManager开始的;它是用来管理Cache(缓存)的,一个应用可以有多个CacheManager,而一个CacheManager下又可以有多个Cache;Cache内部保存的是一个个的Element,而一个Element中保存的是一个key和value的配对,相当于Map里面的一个Entry。
IT云清
2022/05/07
1.5K0
一次springboot和redis缓存的实践
性能缓慢是开发人员经常面临的一个反复出现且复杂的问题。解决此类问题的最常见方法之一是通过缓存。实际上,这种机制允许在任何类型的应用程序的性能方面实现显着改进。问题是处理缓存并不是一件容易的事。幸运的是,Spring Boot 透明地提供了缓存,这要归功于 Spring Boot 缓存抽象,这是一种允许一致使用各种缓存方法而对代码影响最小的机制。让我们看看开始处理它应该知道的一切。
用户4235284
2022/12/05
5650
【SpringBoot2.0系列08】SpringBoot之redis数据缓存管理
【SpringBoot2.0系列02】SpringBoot之使用Thymeleaf视图模板
yukong
2018/08/20
6820
“8个步骤”手把手带你用SpringBoot操作Redis,实现数据缓存!
我们日常生活中,经常会接触听到缓存这个词,例如,浏览器清空缓存,处理器缓存大小,磁盘缓存等等。经过分类,可以将缓存分为:
Java程序猿
2021/05/16
12.3K0
【Redis】SpringBoot集成Redis分布式锁以及Redis缓存
第二个spring-boot-start-cache的依赖,是使用缓存注解需要的,我在项目中没有引入。 因为我在websocket中已经引入了。 查询依赖关系 ctrl+shift+alt+u 快捷键(也可以在pom.xml文件上右键->Maven->Show Dependencies…)查询maven包依赖引入关系,ctrl+f搜索包
谙忆
2021/01/21
1K0
张三进阶之路 | 基于Spring Cache实现缓存技术
张三在面对公司现有缓存技术使用混乱、效果不佳的问题时,选择主动出击,基于Spring框架自研一套缓存解决方案,这体现了他的专业技术能力、问题解决意识以及积极的工作态度。以下是他可能采取的一些关键步骤和考量:
不惑
2024/04/28
6840
张三进阶之路 | 基于Spring Cache实现缓存技术
使用Spring Boot实现博客管理系统
博客管理系统在内容创作和分享中扮演着重要角色。它能够帮助用户方便地发布、编辑、管理和分享博客文章。Spring Boot通过其简便的配置和强大的功能支持,使得开发一个高效的博客管理系统变得非常容易。本文将详细探讨如何使用Spring Boot实现一个博客管理系统,并提供具体的代码示例和应用案例。
E绵绵
2024/07/03
4140
重学SpringBoot3-集成Redis(二)之注解驱动
Spring Boot 提供了对缓存的简便支持,使得开发者能够通过简单的注解实现缓存操作,减少重复代码的编写。本文将详细介绍如何在 Spring Boot 3 中使用 Redis 作为缓存,并通过注解驱动的方式进行缓存操作。
CoderJia
2024/10/18
4980
重学SpringBoot3-集成Redis(二)之注解驱动
Spring学习笔记(三十二)——SpringBoot中cache缓存的介绍和使用
cache 是一个高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载。它通过在内存中缓存数据和对象来减少读取数据库的次数,从而提供动态、数据库驱动网站的速度。
不愿意做鱼的小鲸鱼
2022/09/26
3.4K0
Spring学习笔记(三十二)——SpringBoot中cache缓存的介绍和使用
SpringBoot与Redis
“spring-data-redis” 是 Spring 框架为 Redis 提供的简化抽象。底层可以支持Jedis、Lettuce 等客户端API(Spring Boot 2.x 后Lettuce为默认客户端API),并提供RedisTemplatehe、Repository和整合Spring缓存等多种简便的使用方式。
用户10175992
2022/11/15
6040
【详解】Memcached与Spring提供的cache接口整合
在现代Web应用开发中,缓存技术是提高系统性能和响应速度的重要手段之一。Memcached作为一个高性能的分布式内存对象缓存系统,在许多大型网站和应用中被广泛使用。而Spring框架作为Java企业级开发中的主流框架,提供了强大的缓存抽象层——​​@Cacheable​​、​​@CachePut​​、​​@CacheEvict​​等注解,使得开发者可以非常方便地集成各种缓存解决方案。
大盘鸡拌面
2025/07/05
1710
SpringBoot2.0 基础案例(13):基于Cache注解模式,管理Redis缓存
从Spring3开始定义Cache和CacheManager接口来统一不同的缓存技术; Cache接口为缓存的组件规范定义,包含缓存的各种操作集合; Cache接口下Spring提供了各种缓存的实现; 如RedisCache,EhCacheCache ,ConcurrentMapCache等;
知了一笑
2019/07/19
7040
Spring 整合 Redis
这里配置就完成了。可以直接在service方法上面开启注解: 有4个注解@Cacheable,@CachePut , @CacheEvict,@CacheConfig @Cacheable、@CachePut、@CacheEvict 注释介绍 @Cacheable 作用和配置方法 @Cacheable 的作用 主要针对方法配置,能够根据方法的请求参数对其结果进行缓存 @Cacheable 主要的参数 value 缓存的名称,在 spring 配置文件中定义,必须指定至少一个例如:这里和上面的name 的value对应,楼主这里写的是common @Cacheable(value=”mycache”) 或者 @Cacheable(value={”cache1”,”cache2”} key 缓存的 key,可以为空,如果指定要按照 SpEL 表达式编写,如果不指定,则缺省按照方法的所有参数进行组合例如: @Cacheable(value=”testcache”,key=”#userName”) condition 缓存的条件,可以为空,使用 SpEL 编写,返回 true 或者 false,只有为 true 才进行缓存例如: @Cacheable(value=”testcache”,condition=”#userName.length()>2”)
試毅-思伟
2018/09/06
5820
SpringBoot 实战 (十一) | 整合数据缓存 Cache
如题,今天介绍 SpringBoot 的数据缓存。做过开发的都知道程序的瓶颈在于数据库,我们也知道内存的速度是大大快于硬盘的,当需要重复获取相同数据时,一次又一次的请求数据库或者远程服务,导致大量时间耗费在数据库查询或远程方法调用上,导致性能的恶化,这便是数据缓存要解决的问题。
JavaFish
2019/10/17
2.2K0
SpringBoot 实战 (十一) | 整合数据缓存 Cache
推荐阅读
相关推荐
解释SpringBoot之Ehcache 2.x缓存
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档