当前位置: 首页 > news >正文

点评项目(Redis中间件)数据操作相关知识总结

缓存简介 

无论在哪一层,缓存都遵循着类似的原则:

  1. 检查:当需要获取数据时,首先检查高速的缓存中是否存在。

  2. 命中:如果存在(缓存命中 - Cache Hit),直接从缓存中读取,速度极快。

  3. 未命中:如果不存在(缓存未命中 - Cache Miss),则从速度较慢的主存储中读取数据,同时将一份数据副本存入缓存中,以便下次使用。

计算机组成相关知识点

内存 (Memory / RAM - Random Access Memory)

  • 比喻工厂的工作台。工人在生产产品(CPU在处理数据)时,需要把原材料和工具都放在手边的工作台上。这个工作台的大小决定了能同时摆放多少东西,直接影响工作效率。

  • 官方解释:内存是计算机的主存储器,也叫随机存取存储器。它的特点是:

    • 高速:比磁盘快成千上万倍,CPU可以直接与之高速交换数据。

    • 易失性:需要持续供电来保存数据。一旦断电,工作台上所有东西(数据)都会消失。

    • 作用:用来临时存放正在运行的操作系统、应用程序和当前正在处理的数据。当你打开一个软件或文件时,它们就从磁盘被加载到内存中,CPU再从内存中读取数据进行处理。

  • 关键点:内存决定了你的电脑能同时流畅运行多少个程序。8GB内存的工作台比4GB的大,能同时放下更多东西而不需要频繁地收拾(与磁盘交换)。

磁盘 (Disk / Storage)

  • 比喻仓库后方的大货架。这里存放着所有的原材料、成品和工具。货架很大,能放很多东西,但取用东西需要走过去拿,速度很慢。

  • 官方解释:磁盘是计算机的外部存储器辅助存储器,主要用于长期持久化地保存数据。它的特点是:

    • 非易失性:断电后数据不会丢失。你的操作系统、软件、文档、照片等都保存在这里。

    • 速度慢:相比内存,它的读写速度非常慢(机械硬盘尤甚)。

    • 容量大:通常以GB、TB为单位,远大于内存容量。

  • 常见类型

    • HDD (Hard Disk Drive, 机械硬盘):像老式的唱片机,通过磁头在旋转的盘片上读写数据。优点是便宜、容量大;缺点是速度慢、怕震动、有噪音。

    • SSD (Solid State Drive, 固态硬盘):像超大号的U盘,使用闪存芯片存储数据。优点是速度极快(远超HDD,接近内存)、抗震、无噪音;缺点是价格相对较高(但已大幅下降),寿命有写入次数限制(但对普通用户影响很小)。

  • 关键点:磁盘(特别是SSD)的速度极大影响了电脑的开机速度、软件启动速度和文件加载速度。现在,SSD几乎是提升电脑体验最有效的升级。

缓存 (Cache)

  • 比喻工作台旁边的一个小工具盒。工人(CPU)最常用的一些螺丝刀和零件(数据)会从工作台(内存)上拿过来,放在这个触手可及的小盒子里,用的时候几乎不用弯腰,极大提高了效率。

  • 官方解释:缓存是一小块高速存储器,它的存在是为了弥补CPU超高速和内存相对较慢之间的速度差距

    • 位置:通常直接集成在CPU内部或非常靠近CPU的地方。

    • 速度:比内存快得多,但容量很小(KB或MB级别)。

    • 原理:CPU要读取数据时,首先去缓存里找(这叫做“缓存命中”),如果找到了就直接使用,速度极快。如果没找到(“缓存未命中”),才去内存里取,同时会把这份数据及其周围的数据也复制一份到缓存里,因为根据“局部性原理”,CPU接下来很可能还会用到它们。

  • 层级:通常分为L1、L2、L3三级缓存,L1最小最快,L3最大最慢(但依然远快于内存)。

  • 关键点:缓存是CPU高效工作的关键,它的设计直接影响了CPU的性能。

数据库索引 (Database Index)

  • 比喻教科书最后的“索引”页。你想在一本厚厚的教科书里找到“缓存”这个概念,一页一页翻(全表扫描)非常慢。但如果你先翻到书后的索引,它会告诉你“缓存:第123页”,你就能直接翻到那一页,效率极高。

  • 官方解释:索引是数据库管理系统中一种特殊的查找表,它就像是数据的目录。它能够极大地加快数据库的查询速度

    • 本质:索引是一种数据结构(最常用的是B-Tree/B+Tree),它保存了表中一列或多列的值与其物理存储位置的映射关系。

    • 工作原理

      1. 没有索引:数据库要执行SELECT * FROM users WHERE name = 'Alice';,它必须扫描整个users表,逐行对比,这叫全表扫描,非常慢。

      2. 有索引(在name字段上):数据库会先去name索引这个“目录”里快速找到Alice这个值,索引直接告诉你这条记录存储在磁盘的哪个扇区,然后数据库直接去那个位置读取即可,速度极快。

    • 代价

      • 占用空间:索引本身也需要占用磁盘和内存空间。

      • 降低写操作速度:当你对表进行增、删、改操作时,数据库不仅需要修改表数据,还需要更新对应的索引,这会带来额外的开销。

    • 关键点索引是用空间换时间的经典策略。正确的索引对查询性能提升巨大,但不宜滥用,通常只为经常用于查询条件的字段创建索引。

添加Redis缓存

先从redis里面获取店铺 ,要先获取redis对象,然后再根据key取值,我们这里学习所以用string类型,然后判断是否为空,然后反序列化把字符串转换成对象。

不存在则查询数据库,数据库也没有就直接返回错误,存在就要存储到Redis里面。

缓存更新策略

有缓存和数据库的数据不一致的问题

就上面两种情况,因为数据库的操作速度是远远低于缓存的,所以对于第二种情况,出现线程安全的概率远远低于第一种情况。但是第二种出现问题的情况仍然可能出现,所以我们后期会使用超时剔除。

mybatis-plus回顾

环境搭建

pom文件

<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><!-- 项目基本信息 --><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.5.0</version><relativePath/></parent><groupId>com.itheima</groupId><artifactId>mybatisplus_02_dql</artifactId><version>0.0.1-SNAPSHOT</version><name>MyBatisPlus DQL Project</name><description>MyBatisPlus Dynamic Query Language Example Project</description><!-- 属性配置 --><properties><java.version>1.8</java.version><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding><mybatisplus.version>3.4.1</mybatisplus.version><druid.version>1.1.16</druid.version></properties><!-- 依赖管理 --><dependencies><!-- Spring Boot Starter --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId></dependency><!-- MyBatis Plus --><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>${mybatisplus.version}</version></dependency><!-- Druid 数据库连接池 --><dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>${druid.version}</version></dependency><!-- MySQL 驱动 --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><scope>runtime</scope></dependency><!-- Lombok --><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><!-- 测试依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies><!-- 构建配置 --><build><plugins><!-- Spring Boot Maven 插件 --><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><configuration><excludes><exclude><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></exclude></excludes></configuration></plugin><!-- 编译插件 --><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><configuration><source>${java.version}</source><target>${java.version}</target><encoding>${project.build.sourceEncoding}</encoding></configuration></plugin></plugins></build>
</project>

编写接口

@Mapperpublic interface UserDao extends BaseMapper<User> {}

编写模型类

@Datapublic class User {private Long id;private String name;private String password;private Integer age;private String tel;}

编写引导类

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

编写配置文件

# 数据源配置
spring:datasource:# 连接池类型type: com.alibaba.druid.pool.DruidDataSource# 驱动类名driver-class-name: com.mysql.cj.jdbc.Driver# 数据库连接URLurl: jdbc:mysql://localhost:3306/mybatisplus_db?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8&useSSL=false# 数据库用户名username: root# 数据库密码password: root# Druid连接池特定配置druid:# 初始化连接数initial-size: 5# 最小空闲连接数min-idle: 5# 最大活跃连接数max-active: 20# 获取连接等待超时时间(毫秒)max-wait: 60000# 配置间隔多久才进行一次检测,检测需要关闭的空闲连接(毫秒)time-between-eviction-runs-millis: 60000# 连接保持空闲而不被驱逐的最小时间(毫秒)min-evictable-idle-time-millis: 300000# 测试连接的SQLvalidation-query: SELECT 1# 申请连接时执行validationQuery检测连接是否有效test-while-idle: true# 获取连接时执行validationQuery检测连接是否有效test-on-borrow: false# 归还连接时执行validationQuery检测连接是否有效test-on-return: false# MyBatis Plus配置
mybatis-plus:# 全局配置global-config:db-config:# 主键类型id-type: auto# 表名下划线转驼峰table-underline: true# 列名下划线转驼峰column-underline: true# 配置configuration:# 日志实现log-impl: org.apache.ibatis.logging.stdout.StdOutImpl# 开启驼峰命名映射map-underscore-to-camel-case: true# 缓存启用cache-enabled: true# 延迟加载启用lazy-loading-enabled: true# 延迟加载触发方法lazy-load-trigger-methods: ""# 默认执行器default-executor-type: simple# 查询超时时间(秒)default-statement-timeout: 30# 日志配置
logging:level:# MyBatis Plus日志级别com.itheima.mapper: debug# Spring框架日志级别org.springframework: info# 日志文件输出路径file:name: logs/application.log# 日志模式pattern:console: "%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n"

编写测试类

package com.itheima;import com.itheima.dao.UserDao;
import com.itheima.entity.User;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;import java.util.List;import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertNotNull;/*** MyBatisPlus应用测试类* 用于测试用户数据访问功能* * @author itheima* @version 1.0* @since 2023*/
@SpringBootTest
@DisplayName("用户数据访问层测试")
class Mybatisplus02DqlApplicationTests {@Autowiredprivate UserDao userDao;/*** 测试获取所有用户数据* 验证用户数据访问层的基本查询功能*/@Test@DisplayName("测试获取所有用户")void testGetAllUsers() {// 执行查询List<User> userList = userDao.selectList(null);// 验证结果assertNotNull(userList, "用户列表不应为空");assertThat(userList).isNotEmpty().hasSizeGreaterThan(0);// 输出结果(仅用于开发调试)System.out.println("查询到的用户数量: " + userList.size());userList.forEach(user -> System.out.println("用户信息: " + user.toString()));// 验证每个用户的必要字段userList.forEach(user -> {assertThat(user.getId()).isNotNull();assertThat(user.getName()).isNotBlank();});}/*** 测试上下文加载* 验证Spring应用上下文是否正确配置*/@Test@DisplayName("测试应用上下文加载")void testContextLoads() {assertNotNull(userDao, "UserDao应该被正确注入");}/*** 测试数据库连接* 验证数据库连接是否正常*/@Test@DisplayName("测试数据库连接")void testDatabaseConnection() {long count = userDao.selectCount(null);assertThat(count).isGreaterThanOrEqualTo(0);System.out.println("数据库中的用户总数: " + count);}
}

spring整合mybatis使用方法

导入依赖

<dependencies><!-- Spring Context (包含核心功能) --><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.3.23</version> <!-- 请使用最新版本 --></dependency><!-- Spring JDBC (用于数据源和事务管理) --><dependency><groupId>org.springframework</groupId><artifactId>spring-jdbc</artifactId><version>5.3.23</version></dependency><!-- MyBatis --><dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.5.10</version> <!-- 请使用最新版本 --></dependency><!-- MyBatis-Spring 适配器 (最关键) --><dependency><groupId>org.mybatis</groupId><artifactId>mybatis-spring</artifactId><version>2.0.7</version> <!-- 请使用最新版本 --></dependency><!-- 数据库连接池 (以 HikariCP 为例) --><dependency><groupId>com.zaxxer</groupId><artifactId>HikariCP</artifactId><version>4.0.3</version></dependency><!-- MySQL 驱动 --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.32</version> <!-- 注意与你的MySQL服务器版本匹配 --></dependency>
</dependencies>

编写模型类

// User.java
public class User {private Long id;private String name;private Integer age;private String email;// 省略 getter, setter, toString 方法
}

创建mapper接口

// UserMapper.java
public interface UserMapper {User selectUserById(Long id);List<User> selectAllUsers();int insertUser(User user);int updateUser(User user);int deleteUserById(Long id);
}

sql注入

文件注入
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.yourpackage.mapper.UserMapper"> <!-- 必须是Mapper接口的全限定名 --><sql id="Base_Column_List">id, name, age, email</sql><select id="selectUserById" resultType="com.yourpackage.entity.User">SELECT<include refid="Base_Column_List"/>FROM userWHERE id = #{id}</select><select id="selectAllUsers" resultType="com.yourpackage.entity.User">SELECT<include refid="Base_Column_List"/>FROM user</select><insert id="insertUser" parameterType="com.yourpackage.entity.User" useGeneratedKeys="true" keyProperty="id">INSERT INTO user (name, age, email)VALUES (#{name}, #{age}, #{email})</insert><!-- 其他 update, delete 语句 -->
</mapper>
注解注入
// UserMapper.java
public interface UserMapper {// 1. 最简单的查询@Select("SELECT * FROM user WHERE id = #{id}")User selectUserById(Long id);// 2. 查询所有用户@Select("SELECT * FROM user")List<User> selectAllUsers();// 3. 插入用户,并返回自增主键@Insert("INSERT INTO user (name, age, email) VALUES (#{name}, #{age}, #{email})")@Options(useGeneratedKeys = true, keyProperty = "id") // keyProperty 指实体类中的主键属性名int insertUser(User user);// 4. 更新用户@Update("UPDATE user SET name=#{name}, age=#{age}, email=#{email} WHERE id=#{id}")int updateUser(User user);// 5. 删除用户@Delete("DELETE FROM user WHERE id = #{id}")int deleteUserById(Long id);// 6. 使用 @Param 注解处理多个参数@Select("SELECT * FROM user WHERE name = #{name} AND age > #{age}")List<User> selectUsersByNameAndAge(@Param("name") String name, @Param("age") Integer age);// 7. 复杂结果映射 - 使用 @Results 和 @Result// 假设数据库字段是 user_name,而实体类属性是 name,需要手动映射@Results(id = "userResultMap", value = {@Result(property = "id", column = "id", id = true), // id=true 表示这是主键@Result(property = "name", column = "user_name"), // 映射数据库字段 user_name 到属性 name@Result(property = "email", column = "email_address") // 映射数据库字段 email_address 到属性 email})@Select("SELECT id, user_name, email_address FROM user WHERE id = #{id}")User selectUserWithComplexMapping(Long id);// 8. 引用上面定义的结果映射@ResultMap("userResultMap") // 引用上面 @Results 的 id@Select("SELECT id, user_name, email_address FROM user")List<User> selectAllUsersWithComplexMapping();
}

核心配置类

  • 数据源 (DataSource)

  • SqlSessionFactoryBean:Spring 会用它来创建 MyBatis 的 SqlSessionFactory

  • MapperScannerConfigurer自动扫描 Mapper 接口并注册为 Spring Bean。

// AppConfig.java
@Configuration
@ComponentScan("com.yourpackage") // 扫描你的@Service, @Component等
@EnableTransactionManagement // 启用注解式事务管理
public class AppConfig {// 1. 配置数据源 (以HikariCP为例)@Beanpublic DataSource dataSource() {HikariDataSource dataSource = new HikariDataSource();dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/your_database?useSSL=false&serverTimezone=UTC");dataSource.setUsername("your_username");dataSource.setPassword("your_password");dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");return dataSource;}// 2. 配置SqlSessionFactoryBean@Beanpublic SqlSessionFactoryBean sqlSessionFactory(DataSource dataSource) throws Exception {SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();sessionFactory.setDataSource(dataSource); // 注入数据源// 设置Mapper XML文件的位置 (非常重要!)sessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mapper/*.xml"));// 可选:配置MyBatis的其他设置,如别名、驼峰命名映射等org.apache.ibatis.session.Configuration configuration = new org.apache.ibatis.session.Configuration();configuration.setMapUnderscoreToCamelCase(true); // 开启驼峰命名自动映射sessionFactory.setConfiguration(configuration);return sessionFactory;}// 3. 配置Mapper扫描器,自动注册Mapper接口的代理Bean@Beanpublic MapperScannerConfigurer mapperScannerConfigurer() {MapperScannerConfigurer scanner = new MapperScannerConfigurer();scanner.setBasePackage("com.yourpackage.mapper"); // 指定Mapper接口所在的包// 注意:如果使用了多个SqlSessionFactory,这里需要指定,但通常一个就够了// scanner.setSqlSessionFactoryBeanName("sqlSessionFactory");return scanner;}// 4. 配置事务管理器@Beanpublic PlatformTransactionManager transactionManager(DataSource dataSource) {return new DataSourceTransactionManager(dataSource);}
}
  1. DataSource:一切的起点,管理数据库连接池。

  2. SqlSessionFactoryBean

    • 它是一个 FactoryBean,Spring 在初始化它时,内部会调用它的 getObject() 方法。

    • 这个方法会读取你的所有配置(数据源、XML 位置、设置等),最终构建出一个 MyBatis 的核心对象——SqlSessionFactory

    • SqlSessionFactory 是生产 SqlSession 的工厂,而 SqlSession 是执行 SQL 的会话。

  3. MapperScannerConfigurer

    • 它是一个 BeanDefinitionRegistryPostProcessor,会在 Spring 容器初始化早期运行。

    • 它的任务是扫描你指定的包,找到所有 Mapper 接口。

    • 对于每一个 Mapper 接口,它会向 Spring 容器注册一个 MapperFactoryBean

    • MapperFactoryBean 也是一个 FactoryBean,它会利用第 2 步创建的 SqlSessionFactory,为 Mapper 接口生成一个动态代理的实现类对象

    • 最终,这个代理对象会被注册为 Spring Bean(Bean 的名称通常是接口名首字母小写,如 userMapper)。

  4. PlatformTransactionManager

    • 为 Spring 的声明式事务(@Transactional)提供支持,确保数据库操作在事务内进行。


文章转载自:

http://tidTyZPL.xgLgm.cn
http://iFJG0E7f.xgLgm.cn
http://fYfbxG4p.xgLgm.cn
http://uKFBsI4j.xgLgm.cn
http://FhmJI59O.xgLgm.cn
http://jir1BS7M.xgLgm.cn
http://J4jzDSYy.xgLgm.cn
http://csCbKiPH.xgLgm.cn
http://AarGBr2N.xgLgm.cn
http://ggbedEn1.xgLgm.cn
http://sfeqZo1o.xgLgm.cn
http://R7T0MZ8N.xgLgm.cn
http://5vTzztnv.xgLgm.cn
http://aCzalouJ.xgLgm.cn
http://GcqS73QP.xgLgm.cn
http://m8wN9UaQ.xgLgm.cn
http://MlnG5XE8.xgLgm.cn
http://fZITGDww.xgLgm.cn
http://QMFfVsfP.xgLgm.cn
http://gfvY0gBJ.xgLgm.cn
http://pPqoOkmw.xgLgm.cn
http://Avy5PCZu.xgLgm.cn
http://QHMkvu25.xgLgm.cn
http://4feu6mxn.xgLgm.cn
http://JPAvrWxQ.xgLgm.cn
http://pwjIf9Oo.xgLgm.cn
http://zlx1teMi.xgLgm.cn
http://TCmIjAYJ.xgLgm.cn
http://1Sb5ovsL.xgLgm.cn
http://cXfO62Kz.xgLgm.cn
http://www.dtcms.com/a/387747.html

相关文章:

  • 从0死磕全栈第九天:Trae AI IDE一把梭,使用react-query快速打通前后端接口调试
  • 【论文阅读】MIDAS: 多模态交互式数字人合成,通过实时自回归视频生成
  • 为什么React Native 中点到了却不动
  • 学习React-13-useLayoutEffect
  • Redis-更新策略
  • 7、二叉树-四种遍历方式
  • 双指针:逛画展
  • 数字孪生能源大数据云平台建设方案
  • WPSOffice引用的组件
  • 按键分区和非按键分区对窗口计算的影响
  • 2020年下半年 系统架构设计师 综合知识
  • 传感器与传感网 | 第一章:传感器与感知技术
  • 在Jupyter Notebook里面渲染pyecharts无法显示
  • 在 React 项目里下载 CSV 文件常见的两种方式
  • 【脑电分析系列】第15篇:脑电功能连接性与脑网络分析(二):Granger因果性、图论指标与复杂网络构建
  • SpringMVC 系列博客(一):基础概念与注解开发入门
  • AI+Playwright+Pytest 自动化测试方案:优势、劣势与实战融合
  • docker启动Nginx并配置SSL自动续期.md
  • OpenStack 学习笔记(三):存储与计算核心组件管理实践
  • Linux文件IO与文件系统深度解析:从系统调用到文件系统原理
  • 如何在 2025 年绕过 Cloudflare 人工检查?
  • 【pycharm】index-tts2:之三 :ubuntu24.04 体验tts demo
  • vivado中DDR4 仿真模型的获取
  • 《RocketMQ 2025 实战指南:从消息丢失 / 重复消费 / 顺序消费到事务消息,一篇搞定生产级问题(附完整代码)》
  • 十二、vue3后台项目系列——设置路由守卫,获取角色权限,获取角色路由列表、页面请求进度条
  • 6个AI论文网站排行,实测
  • Dioxus基础介绍和创建组件
  • 基于粒子群算法的山地环境无人机最短路径规划研究(含危险区域约束的三维优化方法)
  • ardupilot开发 --- 无人机数学模型与控制律分解 篇
  • 海外代理IP服务器平台测评,Tik Tok多账号运营稳定IP服务支持