Spring Boot整合Redis缓存实现

本文详细介绍了如何在SpringBoot项目中整合JPA、MyBatis和Redis,实现数据访问及缓存管理。首先创建SpringBoot项目并配置数据库连接,接着编写实体类、Repository接口、Service业务类和Controller控制层。然后通过注解配置Redis缓存,包括基于注解的缓存管理和API操作缓存。最后,自定义Redis序列化机制以确保数据正确序列化和反序列化。通过这些步骤,实现了高效的数据库操作和缓存策略。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

准备数据
使用“Spring Boot数据访问,整合MyBatis,JPA,Redis”文章使用到的数据库springbootdata
创建项目
创建Spring Boot项目引入JPA、MySQL、Web依赖
编写数据库表对应的实体类
新建domain包,在该包下编写数据库表t_comment对应的实体类Comment,并使用JPA相关注解配置映射关系

import javax.persistence.*;
import java.io.Serializable;

@Entity(name = "t_comment")
public class Comment{
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;
    private String content;
    private String author;
    @Column(name = "a_id") //指定映射的表字段名
    private Integer aId;

    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 String getAuthor() {
        return author;
    }

    public void setAuthor(String author) {
        this.author = author;
    }

    public Integer getaId() {
        return aId;
    }

    public void setaId(Integer aId) {
        this.aId = aId;
    }

    @Override
    public String toString() {
        return "Comment{" +
                "id=" + id +
                ", content='" + content + '\'' +
                ", author='" + author + '\'' +
                ", aId=" + aId +
                '}';
    }
}

编写数据库操作的Repository接口文件
新建repository包,在该包下创建一个用于操作Comment实体的Repository接口,该接口继承JpaRepository

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.transaction.annotation.Transactional;
import zzd.example.chapter06.domain.Comment;

public interface CommentRespository extends JpaRepository<Comment,Integer> {
    //根据评论id修改评论作者author
    @Transactional
    @Modifying
    @Query("UPDATE t_comment c SET c.author = ?1 WHERE c.id = ?2")
    public int updateComment(String author,Integer id);
}

编写业务操作类Service文件
新建service包,在该包下创建一个用于Comment相关业务模块操作的Service实体类

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import zzd.example.chapter06.domain.Comment;
import zzd.example.chapter06.repository.CommentRespository;

import java.util.Optional;

@Service
public class CommentService {
    @Autowired
    private CommentRespository commentRespository;
    //根据评论id查询评论信息
    public Comment findById(int comment_id){
        Optional<Comment> optional = commentRespository.findById(comment_id);
        if (optional.isPresent()){
            return optional.get();
        }
        return null;
    }
    public Comment updateComment(Comment comment){
        commentRespository.updateComment(comment.getAuthor(),comment.getaId());
        return comment;
    }
    public void deleteComment(int comment_id){
        commentRespository.deleteById(comment_id);
    }
}

编写Web访问层Controller文件
新建controller包,在该包下创建一个用于Comment访问控制的Controller实体类

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import zzd.example.chapter06.domain.Comment;
import zzd.example.chapter06.service.CommentService;

@RestController
public class CommentController {
    @Autowired
    private CommentService commentService;
    @GetMapping("/get/{id}")
    public Comment findById(@PathVariable("id") int comment_id){
        Comment comment = commentService.findById(comment_id);
        return comment;
    }
    @GetMapping("/update/{id}/{author}")
    public Comment upfdateComment(@PathVariable("id") int comment_id,@PathVariable("author") String author){
        Comment comment = commentService.findById(comment_id);
        comment.setAuthor(author);
        Comment updateComment = commentService.updateComment(comment);
        return updateComment;
    }
    @GetMapping("/delete/{id}")
    public void deleCopmment(@PathVariable("id") int comment_id){
        commentService.deleteComment(comment_id);
    }
}

编写全局配置文件

#MySQL数据库连接配置
spring.datasource.url=jdbc:mysql://localhost:3306/springbootdata?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=123456
#显示使用JPA进行数据库查询的SQL语句
spring.jpa.show-sql=true

基于注解的Redis缓存实现
添加Spring Data Redis依赖启动器

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>

Redis服务连接配制,在全局文件中添加Redis服务的连接配置

#Redis服务器地址
spring.redis.host=192.168.110.110
#Redis服务器连接端口
spring.redis.port=6379
#Redis服务器连接密码(默认为空)
#spring.redis.password=
#对基于注解的Redis缓存数据同意设置有效期为1分钟,单位毫秒
spring.cache.redis.time-to-live=60000

对CommentService类中的方法进行修改,使用@Cacheable、@CachePut、@CacheEvict3个注解制定缓存管理

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import zzd.example.chapter06.domain.Comment;
import zzd.example.chapter06.repository.CommentRespository;

import java.util.Optional;

@Service
public class CommentService {
    @Autowired
    private CommentRespository commentRespository;
    //根据评论id查询评论信息
    //查询缓存
    @Cacheable(cacheNames = "comment",unless = "#result==null")
    public Comment findById(int comment_id){
        Optional<Comment> optional = commentRespository.findById(comment_id);
        if (optional.isPresent()){
            return optional.get();
        }
        return null;
    }
    //更新缓存
    @Cacheable(cacheNames = "comment",key="#result.id")
    public Comment updateComment(Comment comment){
        commentRespository.updateComment(comment.getAuthor(),comment.getaId());
        return comment;
    }
    //删除缓存
    @CacheEvict(cacheNames = "comment")
    public void deleteComment(int comment_id){
        commentRespository.deleteById(comment_id);
    }
}

将缓存对象实现序列化、实体类实现JDK自带序列化接口Serializable

import javax.persistence.*;
import java.io.Serializable;

@Entity(name = "t_comment")
public class Comment implements Serializable{
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;
    private String content;
    private String author;
    @Column(name = "a_id") //指定映射的表字段名
    private Integer aId;

    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 String getAuthor() {
        return author;
    }

    public void setAuthor(String author) {
        this.author = author;
    }

    public Integer getaId() {
        return aId;
    }

    public void setaId(Integer aId) {
        this.aId = aId;
    }

    @Override
    public String toString() {
        return "Comment{" +
                "id=" + id +
                ", content='" + content + '\'' +
                ", author='" + author + '\'' +
                ", aId=" + aId +
                '}';
    }
}

效果测试
项目启动成功,通过浏览器访问:http://licalhost:8080/get/1 不管刷新多少次控制都只打印一次
在这里插入图片描述
在这里插入图片描述
在配置类中统一配置Redis数据的有效期,这种方式相对来说不过灵活,并且这种设置对基于API的Redis换成实现没有效果
基于API的Redis缓存实现
使用RedisAPI进行业务数据缓存管理
在service包下编写一个业务处理类ApiCommentService

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import zzd.example.chapter06.domain.Comment;
import zzd.example.chapter06.repository.CommentRespository;

import java.util.Optional;
import java.util.concurrent.TimeUnit;

@Service
public class ApiCommentService {
    @Autowired
    private CommentRespository commentRespository;
    @Autowired
    private RedisTemplate redisTemplate;
    public Comment findById(int comment_id){
        //先从Redis缓存中查询数据
        Object object = redisTemplate.opsForValue().get("comment_"+comment_id);
        if (object!=null){
            return (Comment)object;
        }else {
            //缓存中没有,就是进入数据库查询
            Optional<Comment> optional = commentRespository.findById(comment_id);
            if (optional.isPresent()){
                Comment comment = optional.get();
                //将查询结果进行,并设置有效期为1天
                redisTemplate.opsForValue().set("comment_"+comment_id,comment,1, TimeUnit.DAYS);
                return comment;
            }else {
                return null;
            }
        }
    }
    public Comment updateComment(Comment comment){
        commentRespository.updateComment(comment.getAuthor(),comment.getaId());
        //更新数据后进行缓存更新
        redisTemplate.opsForValue().set("comment_"+comment.getId(),comment);
        return comment;
    }
    public void deleteComment(int comment_id){
        commentRespository.deleteById(comment_id);
        //删除数据后进行患处删除
        redisTemplate.delete("comment_"+comment_id);
    }
}

编写Web访问层Controller文件
在controller包下创建Controller实体类

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import zzd.example.chapter06.domain.Comment;
import zzd.example.chapter06.service.ApiCommentService;

@RestController
@RequestMapping("/api")
public class ApiCommentController {
    @Autowired
    private ApiCommentService apiCommentService;
    @GetMapping("/get/{id}")
    public Comment findById(@PathVariable("id") int comment_id){
        Comment comment = apiCommentService.findById(comment_id);
        return  comment;
    }
    @GetMapping("/update/{id}/{author}")
    public Comment updateComment(@PathVariable("id")int comment_id,@PathVariable("author")String author){
        Comment comment = apiCommentService.findById(comment_id);
        comment.setAuthor(author);
        Comment updateComment = apiCommentService.updateComment(comment);
        return updateComment;
    }
    @GetMapping("/delete/{id}")
    public void deleComment(@PathVariable("id")int comment_id){
        apiCommentService.deleteComment(comment_id);
    }
}

在这里插入图片描述
自定义Redis缓存序列化机制
自定义JSON格式的数据序列化机制进行数据缓存管理
RedisAPI默认序列化机制
自定义Redis Template序列化机制
在config包下自定义配置类RedisConfig

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

import java.time.Duration;

@Configuration //自定义一个序列化配置类  实现JSON格式缓存数据
public class RedisConfig {
    @Bean
    public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory){
        RedisTemplate<Object, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(redisConnectionFactory);
        //使用json格式序列化对象,对缓存数据key和value进行转换
        Jackson2JsonRedisSerializer jacksonSeial = new Jackson2JsonRedisSerializer(Object.class);
        //解决查询缓存转换异常的问题
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jacksonSeial.setObjectMapper(om);
        //设置RedisTemplate模板API的序列化方式为Json
        template.setDefaultSerializer(jacksonSeial);
        return template;
    }
}

Redis注解默认序列化机制
自定义RedisCacheManager
在config包下自定义配置类RedisConfig

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

import java.time.Duration;

@Configuration //敌意一个序列化配置类  实现JSON格式缓存数据
public class RedisConfig {
    @Bean
    public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory){
        RedisTemplate<Object, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(redisConnectionFactory);
        //使用json格式序列化对象,对缓存数据key和value进行转换
        Jackson2JsonRedisSerializer jacksonSeial = new Jackson2JsonRedisSerializer(Object.class);
        //解决查询缓存转换异常的问题
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jacksonSeial.setObjectMapper(om);
        //设置RedisTemplate模板API的序列化方式为Json
        template.setDefaultSerializer(jacksonSeial);
        return template;
    }

    //基于注解的redis缓存实现也使用自定义的序列化机制
    @Bean
    public RedisCacheManager cacheManager(RedisConnectionFactory redisConnectionFactory){
        //分别创建String和json格式序列化对象,对缓存数据key和value进行转换
        RedisSerializer<String> strSerializer = new StringRedisSerializer();
        Jackson2JsonRedisSerializer jacksonSeial = new Jackson2JsonRedisSerializer(Object.class);
        //解决查询缓存准换异常的问题
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL,JsonAutoDetect.Visibility.ANY);
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jacksonSeial.setObjectMapper(om);
        //定制缓存数据序列化方式及时效
        RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
                .entryTtl(Duration.ofDays(1)) //缓存有效期为一天
                .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(strSerializer))  //key的值为string
                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jacksonSeial))  //value的值为json
                .disableCachingNullValues();
        RedisCacheManager cacheManager = RedisCacheManager.builder(redisConnectionFactory).cacheDefaults(config).build();
        return cacheManager;

    }
}
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值