SpringBoot,Mysql,Redis综合案例(2)

StudentService的实现
基本框架
@Service
@Slf4j
public class StudentApplicationImpl extends ServiceImpl<StudentMapper, Student> implements StudentService {

    // 声明StudentMapper对象,用于数据库操作
    private StudentMapper studentMapper;
    // 声明StringRedisTemplate对象,用于Redis字符串类型操作
    private StringRedisTemplate stringRedisTemplate;
    // 声明ValueOperations对象,用于Redis的String类型数据操作
    private ValueOperations<String, String> forValue;
    // 声明ListOperations对象,用于Redis的List类型数据操作
    private ListOperations<String, String> forList;

    // 定义学生信息在Redis中的键前缀常量
    public static final String PREFIX_STUDENT = "PREFIX_STUDENT";
    // 定义存储所有学生信息的Redis键常量
    public static final String ALL_STUDENT = "ALL_STUDENT";

    // 构造方法,通过@Autowired实现依赖注入
    @Autowired
    public StudentApplicationImpl(StudentMapper studentMapper, StringRedisTemplate stringRedisTemplate) {
        // 赋值studentMapper,用于后续数据库操作
        this.studentMapper = studentMapper;
        // 赋值stringRedisTemplate,用于后续Redis操作
        this.stringRedisTemplate = stringRedisTemplate;
        // 初始化forValue,获取Redis的String类型操作对象
        this.forValue = stringRedisTemplate.opsForValue();
        // 初始化forList,获取Redis的List类型操作对象
        this.forList = stringRedisTemplate.opsForList();
    }
}
各功能的实现

根据ID查询学生信息(先查Redis缓存,再查数据库)

@Override
public Student getStudentById(String id) {
    // 打印日志,记录开始查询指定ID的学生数据
    log.info("开始查询id:{}的数据", id);
    // 从Redis中查询指定ID的学生信息(键为前缀+ID)
    String studentJSON = forValue.get(PREFIX_STUDENT + id);
    // 打印日志,记录从Redis查询到的JSON数据
    log.info("返回id:{}的数据:{}", id, studentJSON);
    // 判断Redis中是否存在该学生的缓存数据
    if (studentJSON != null) {
        // 将JSON字符串转换为Student对象并返回
        return JSONArray.parseObject(studentJSON, Student.class);
    }
    // Redis中无缓存,从数据库查询该学生信息
    Student student = studentMapper.selectById(id);
    // 打印日志,记录从数据库查询到的学生数据
    log.info("不存在该数据,从数据库中获取该数据:{}", student);
    // 将数据库查询到的学生对象转换为JSON字符串
    String jsonString = JSONArray.toJSONString(student);
    // 将JSON字符串存入Redis,设置键为前缀+ID,过期时间1天
    forValue.set(PREFIX_STUDENT + id, jsonString,1, TimeUnit.DAYS);
    // 打印日志,记录已将数据存入Redis
    log.info("存放数据到redis中");
    // 返回从数据库查询到的学生对象
    return student;
}

查询所有学生信息(建议方法三)

​ 方法一:

 @Override
    public List<Student> findAllStudent1() {
        // 从Redis中查询所有学生信息(键为ALL_STUDENT)
        String string = forValue.get(ALL_STUDENT);
        // 判断Redis中是否存在所有学生的缓存数据
        if(string != null){
            // 将JSON数组字符串转换为List<Student>并返回
            return JSONArray.parseArray(string, Student.class);
        }
        // Redis中无缓存,从数据库查询所有学生信息
        List<Student> list = this.list();
        // 将数据库查询到的学生列表转换为JSON字符串并存入Redis,设置过期时间1天
        forValue.set(ALL_STUDENT, JSONArray.toJSONString(list),1, TimeUnit.DAYS);
        // 返回从数据库查询到的学生列表
        return list;
    }

​ 方法二:

 @Override
    public List<Student> findAllStudent2() {
        // 从Redis的List结构中查询所有学生信息(0到-1表示查询全部元素)
        List<String> all = forList.range(ALL_STUDENT, 0, -1);
        // 判断Redis中是否存在缓存数据
        if(all != null&&!all.isEmpty()){
            // 初始化学生列表用于存储转换后的数据
            List<Student> list =new ArrayList<>();
            // 遍历Redis中获取的JSON字符串
            all.forEach(s->{
                // 将JSON字符串转换为Student对象
                Student jsonObject = JSONArray.parseObject(s , Student.class);
                // 添加到学生列表中
                list.add(jsonObject);
            });
            // 返回从Redis缓存中获取的学生列表
            return list;
        }
        // Redis中无缓存,从数据库查询所有学生
        List<Student> students = this.list();
        // 将数据库查询结果存入Redis缓存
        students.forEach(student -> {
            // 将Student对象转换为JSON字符串
            String s = JSONArray.toJSONString(student);
            // 向Redis的List尾部添加学生JSON数据
            forList.rightPush(ALL_STUDENT,s);
        });
        // 返回数据库查询的学生列表
        return students;
    }

​ 方法三:

 @Override
    public List<Student> findAllStudent3() {
        // 从Redis的List中查询所有学生ID(0到-1表示查询全部)
        List<String> all = forList.range(ALL_STUDENT, 0, -1);
        // 判断Redis中是否存在缓存的ID列表
        if(all != null&&!all.isEmpty()){
            // 初始化学生列表用于存储查询结果
            List<Student> list =new ArrayList<>();
            // 遍历每个学生ID
            all.forEach(s->{
                // 根据ID从Redis的String结构中获取学生详情JSON
                String string = forValue.get(s);
                // 将JSON字符串转换为Student对象
                Student student = JSONArray.parseObject(string, Student.class);
                // 添加到学生列表中
                list.add(student);
            });
            // 返回从Redis缓存中组装的学生列表
            return list;
        }
        // Redis中无缓存,从数据库查询所有学生
        List<Student> students = this.list();
        // 将数据库查询结果存入Redis缓存(List存ID,String存详情)
        students.forEach(student -> {
            // 向Redis的List尾部添加学生ID
            forList.rightPush(ALL_STUDENT,student.getId()+"");
            // 以学生ID为键,JSON字符串为值存入Redis的String结构
            forValue.set(student.getId()+"",JSONArray.toJSONString(student));
        });
        // 返回数据库查询的学生列表
        return students;
    }

新增学生时同步更新Redis缓存(建议方法二)

​ 方法一:

 @Override
    public int saveStudent(Student student) {
        // 向数据库保存或更新学生信息
        boolean b = this.saveOrUpdate(student);
        // 创建查询条件构造器
        QueryWrapper<Student> queryWrapper = new QueryWrapper<>();
        // 添加查询条件:按姓名和学号查询(确保唯一性)
        queryWrapper.eq("name", student.getName());
        queryWrapper.eq("stu_no",student.getStuNo() );
        // 从数据库查询刚保存的学生信息(获取完整字段,如自动生成的ID)
        Student one = getOne(queryWrapper);
        // 将学生信息同步到Redis缓存
        String jsonString = JSONArray.toJSONString(one);
        // 向Redis的List尾部添加新学生的JSON数据
        forList.rightPush(ALL_STUDENT,jsonString);
        // 根据数据库操作结果返回1(成功)或0(失败)
        return b?1:0;
    }

方法二:

 // 重写saveStudent的另一种实现(注释掉的版本),使用ID作为List元素
    @Override
    public int saveStudent(Student student) {
        // 向数据库保存或更新学生信息
        boolean b = this.saveOrUpdate(student);
        // 创建查询条件构造器
        QueryWrapper<Student> queryWrapper = new QueryWrapper<>();
        // 添加查询条件:按姓名和学号查询
        queryWrapper.eq("name", student.getName());
        queryWrapper.eq("stu_no",student.getStuNo() );
        // 从数据库查询刚保存的学生信息
        Student one = getOne(queryWrapper);
        // 向Redis的List尾部添加学生ID
        forList.rightPush(ALL_STUDENT,one.getId()+"");
        // 以学生ID为键,JSON为值存入Redis的String结构
        forValue.set(one.getId() + "",JSONArray.toJSONString(one));
        // 返回操作结果标识
        return b ? 1 : 0;
    }

更新学生时同步更新Redis缓存(建议方法二)

方法一:

public int updateStudent(Student student) {
        // 根据ID更新数据库中的学生信息
        Boolean b = updateById(student);
        // 创建查询条件构造器
        QueryWrapper<Student> queryWrapper = new QueryWrapper<>();
        // 添加查询条件:按ID查询(获取更新后的完整信息)
        queryWrapper.eq("id", student.getId());
        Student one = getOne(queryWrapper);
        // 从Redis中查询所有学生的JSON列表
        List<String> list = forList.range(ALL_STUDENT, 0, -1);
        // 判断Redis中是否存在缓存数据
        if(list!=null&&!list.isEmpty()){
            // 定义索引变量用于记录List中元素的位置
            final int[] index = {0};
            // 遍历Redis中的学生JSON列表
            list.forEach(e->{
                // 将JSON字符串转换为Student对象
                Student student1 = JSONArray.parseObject(e, Student.class);
                // 判断当前元素是否为需要更新的学生(通过ID匹配)
                if(student1.getId().equals(student.getId())){
                    // 在Redis的List中替换对应位置的元素为更新后的JSON
                    forList.set(ALL_STUDENT, index[0],JSONArray.toJSONString(one));
                }
                // 索引自增,记录下一个元素位置
                index[0]++;
            });
        }
        // 根据数据库操作结果返回1(成功)或0(失败)
        return b ? 1 : 0;
    }

方法二:

@Override
    public int updateStudent(Student student) {
        // 根据ID更新数据库中的学生信息
        Boolean b = updateById(student);
        // 创建查询条件构造器
        QueryWrapper<Student> queryWrapper = new QueryWrapper<>();
        // 添加查询条件:按ID查询
        queryWrapper.eq("id", student.getId());
        // 获取更新后的学生信息
        Student one = getOne(queryWrapper);
        // 如果Redis中存在该学生的缓存,则更新对应的String值
        forValue.setIfPresent(one.getId()+"",JSONArray.toJSONString(one));
        // 返回操作结果标识
        return b?1:0;
    }

删除学生时同步删除Redis缓存

@Override
    public int removeStudentById(String id) {
        // 从数据库中删除指定ID的学生
        boolean b = removeById(id);
        // 从Redis的List中删除包含该ID的元素(1表示删除一个匹配项)
        forList.remove(ALL_STUDENT,1,id+"");
        // 从Redis中删除该ID对应的String缓存
        stringRedisTemplate.delete(id+"");
        // 根据数据库操作结果返回1(成功)或0(失败)
        return b?1:0;
    }
test的实现

​ 在test包下创建StudentApp类实现功能的测试

// 标注该类为Spring Boot测试类,用于测试Spring Boot应用中的组件
@SpringBootTest
// 引入Slf4j日志注解,方便打印日志
@Slf4j
public class StudentApp {

    // 注入StudentService接口的实现类,用于调用学生相关的业务方法
    @Resource
    StudentService studentService;

    // 测试方法:根据ID查询学生信息
    @Test
    public void a(){
        // 调用Service层方法,根据指定ID查询学生
        Student studentById = studentService.getStudentById("1967043343284449283");
        // 打印查询到的学生信息日志
        log.info("studentById:{}", studentById);
    }

    // 测试方法:查询所有学生(使用缓存策略1)
    @Test
    public void b1(){
        // 调用Service层方法,查询所有学生(对应findAllStudent1实现)
        List<Student> allStudent = studentService.findAllStudent1();
        // 打印所有学生信息日志
        log.info("allStudent:{}", allStudent);
    }

    // 测试方法:查询所有学生(使用缓存策略2)
    @Test
    public void b2(){
        // 调用Service层方法,查询所有学生(对应findAllStudent2实现)
        List<Student> allStudent = studentService.findAllStudent2();
        // 注释掉直接打印列表的方式,改为遍历打印每个学生信息(避免日志过长)
//        log.info("allStudent:{}", allStudent);
        allStudent.forEach(e->{
            log.info("e:{}", e);
        });
    }

    // 测试方法:查询所有学生(使用缓存策略3)
    @Test
    public void b3(){
        // 调用Service层方法,查询所有学生(对应findAllStudent3实现)
        List<Student> allStudent = studentService.findAllStudent3();
        // 遍历打印每个学生信息
        allStudent.forEach(e->{
            log.info("e:{}", e);
        });
    }

    // 测试方法:新增学生信息
    @Test
    public void c(){
        // 创建学生对象并设置属性
        Student student=new Student();
        student.setName("aaa");
        student.setPlaceOfOrigin("陕西西安");
        student.setCourseId(1965250158253547036L);
        student.setSchoolId(1965321181514842113L);
        student.setBirthday("2003-9-19");
        student.setStuNo("RG2025092837822");
        student.setGender('男');
        // 调用Service层方法保存学生信息,接收操作结果(1成功,0失败)
        int i = studentService.saveStudent(student);
        // 打印操作结果日志
        log.info("i:{}", i);
    }

    // 测试方法:更新学生信息
    @Test
    public void d(){
        // 创建学生对象,设置需要更新的ID和字段(此处更新生日)
        Student student = new Student();
        student.setId(1967043343284449283L);
        student.setBirthday("2003-9-21");
        // 调用Service层方法更新学生信息,接收操作结果
        int row = studentService.updateStudent(student);
        // 打印操作结果日志
        log.info("row:{}", row);
    }

    // 测试方法:根据ID删除学生信息
    @Test
    public void e(){
        // 调用Service层方法,根据指定ID删除学生
        studentService.removeStudentById("1967043343284449283");
    }
}
Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐