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

mybatis的第五天学习笔记

12. 动态SQL

12.1 动态SQL概述

新增内容:
  1. 动态SQL执行流程

    • MyBatis如何解析动态SQL
    • SQL语句构建过程
    • 参数绑定机制
  2. 新增示例

    // 动态条件查询接口示例
    List<User> searchUsers(@Param("name") String name,@Param("age") Integer age,@Param("email") String email);
    
    <!-- 动态条件查询XML示例 -->
    <select id="searchUsers" resultType="user">SELECT * FROM users<where><if test="name != null">AND name LIKE #{name}</if><if test="age != null">AND age = #{age}</if><if test="email != null">AND email = #{email}</if></where>
    </select>
    
  3. 最佳实践

    • 使用@Param注解明确参数名
    • 保持动态SQL简洁
    • 避免过度嵌套

动态SQL是指在SQL语句中根据不同的条件动态拼接SQL语句。在实际开发中,我们经常需要根据用户输入的不同条件来构建不同的SQL语句。

版本兼容性
  • MyBatis 3.x 全面支持动态SQL
  • 部分标签在早期版本中可能不支持
性能考虑
  1. 动态SQL会增加SQL解析开销
  2. 合理使用可以减少数据库访问次数
  3. 避免过度复杂的动态SQL
常见应用场景
  1. 批量删除

    • 示例SQL:delete from t_car where id in(1,2,3,4,5,6,...)
    • 特点:
      • 需要删除的id值是动态的,根据用户选择的不同而变化
      • 通常用于后台管理系统中的批量操作
    • 实际应用:
      • 电商后台批量删除商品
      • CMS系统批量删除文章
      • 用户管理系统批量删除用户
  2. 多条件查询

    • 示例SQL:select * from t_car where brand like '丰田%' and guide_price > 30 and .....
    • 特点:
      • 查询条件根据用户输入动态变化
      • 条件之间可能存在逻辑关系(AND/OR)
    • 实际应用:
      • 电商平台高级商品筛选
      • CRM系统客户多条件查询
      • 报表系统动态数据筛选
  3. 动态更新

    • 示例SQL:update t_user set username=?, email=? where id=?
    • 特点:
      • 只更新用户提交的字段
      • 避免更新未修改的字段
    • 实际应用:
      • 用户信息编辑页面
      • 商品信息修改
      • 系统配置更新
动态SQL的优势
  1. 提高代码复用性
  2. 减少代码量
  3. 提高开发效率
  4. 使SQL语句更加灵活

12.2 if标签

if标签用于条件判断,根据条件动态拼接SQL语句。它是最基础也是最常用的动态SQL标签。

基本语法
<if test="条件表达式">SQL片段
</if>
示例:多条件查询汽车信息
// Mapper接口
List<Car> selectByMultiCondition(@Param("brand") String brand, @Param("guidePrice") Double guidePrice, @Param("carType") String carType);
<!-- Mapper XML -->
<select id="selectByMultiCondition" resultType="car">select * from t_car where<if test="brand != null and brand != ''">brand like "%"#{brand}"%"</if><if test="guidePrice != null and guidePrice != ''">and guide_price >= #{guidePrice}</if><if test="carType != null and carType != ''">and car_type = #{carType}</if>
</select>
注意事项
  1. 条件判断问题

    • 当第一个条件为空时,SQL语句会出现语法错误(where后面直接跟and)
    • 解决方案:在where后面添加一个恒成立的条件,如:where 1=1
  2. 空值处理

    • 使用!= null!= ''双重判断,确保参数不为空
    • 对于数值类型,还需要考虑0的情况
  3. 参数命名

    • 建议使用@Param注解明确指定参数名称
    • 避免使用模糊的参数名

12.3 where标签

where标签是if标签的增强版,专门用于处理where子句。

主要作用
  1. 自动处理where关键字

    • 当所有条件为空时,不会生成where子句
    • 当至少有一个条件满足时,自动添加where关键字
  2. 自动处理连接词

    • 自动去除条件前面多余的and或or
    • 不能自动去除后面多余的and或or
示例代码
<select id="selectByMultiConditionWithWhere" resultType="car">select * from t_car<where><if test="brand != null and brand != ''">and brand like "%"#{brand}"%"</if><if test="guidePrice != null and guidePrice != ''">and guide_price >= #{guidePrice}</if><if test="carType != null and carType != ''">and car_type = #{carType}</if></where>
</select>
使用建议
  1. 始终将and/or放在条件前面
  2. 不要依赖where标签处理后面的连接词
  3. 对于复杂的条件组合,考虑使用trim标签

12.4 trim标签

trim标签提供了更灵活的条件处理方式,可以自定义前缀、后缀以及要删除的内容。

属性说明
  • prefix:在trim标签中的语句前添加内容
  • suffix:在trim标签中的语句后添加内容
  • prefixOverrides:前缀覆盖掉(去掉)
  • suffixOverrides:后缀覆盖掉(去掉)
示例代码
<select id="selectByMultiConditionWithTrim" resultType="car">select * from t_car<trim prefix="where" suffixOverrides="and|or"><if test="brand != null and brand != ''">brand like "%"#{brand}"%" and</if><if test="guidePrice != null and guidePrice != ''">guide_price >= #{guidePrice} and</if><if test="carType != null and carType != ''">car_type = #{carType}</if></trim>
</select>
使用场景
  1. 需要自定义前缀和后缀
  2. 需要同时处理前后多余的连接词
  3. 复杂的条件组合

12.5 set标签

set标签专门用于update语句,处理set子句。

主要功能
  1. 自动处理set关键字
  2. 自动去除最后多余的逗号
  3. 只更新提交的不为空的字段
示例代码
<update id="updateWithSet">update t_car<set><if test="carNum != null and carNum != ''">car_num = #{carNum},</if><if test="brand != null and brand != ''">brand = #{brand},</if><if test="guidePrice != null and guidePrice != ''">guide_price = #{guidePrice},</if><if test="produceTime != null and produceTime != ''">produce_time = #{produceTime},</if><if test="carType != null and carType != ''">car_type = #{carType},</if></set>where id = #{id}
</update>
使用建议
  1. 每个字段赋值后都要加逗号
  2. 最后一个字段的逗号会被自动去除
  3. 确保至少有一个字段被更新

12.6 choose when otherwise

这三个标签一起使用,实现类似if-else if-else的逻辑。

特点
  1. 只有一个分支会被执行
  2. 按顺序判断条件
  3. 当所有when都不满足时,执行otherwise
示例代码
<select id="selectWithChoose" resultType="car">select * from t_car<where><choose><when test="brand != null and brand != ''">brand like #{brand}"%"</when><when test="guidePrice != null and guidePrice != ''">guide_price >= #{guidePrice}</when><otherwise>produce_time >= #{produceTime}</otherwise></choose></where>
</select>
使用场景
  1. 多条件优先级查询
  2. 条件互斥的场景
  3. 默认查询条件

12.7 foreach标签

foreach标签用于循环处理集合或数组,常用于批量操作。

属性说明
  • collection:集合或数组
  • item:集合或数组中的元素
  • separator:分隔符
  • open:开始符号
  • close:结束符号
  • index:当前元素的索引(可选)
批量删除示例
  1. 使用in方式(推荐):
<delete id="deleteBatchByForeach">delete from t_car where id in<foreach collection="ids" item="id" separator="," open="(" close=")">#{id}</foreach>
</delete>
  1. 使用or方式:
<delete id="deleteBatchByForeach2">delete from t_car where<foreach collection="ids" item="id" separator="or">id = #{id}</foreach>
</delete>
批量添加示例
<insert id="insertBatchByForeach">insert into t_car values <foreach collection="cars" item="car" separator=",">(null,#{car.carNum},#{car.brand},#{car.guidePrice},#{car.produceTime},#{car.carType})</foreach>
</insert>
使用建议
  1. 批量删除优先使用in方式,性能更好
  2. 注意集合参数的处理方式
  3. 考虑批量操作的数据量限制

12.8 sql标签与include标签

这两个标签用于SQL代码复用,提高代码的可维护性。

主要功能
  1. sql标签:声明可重用的SQL片段
  2. include标签:引用已声明的SQL片段
示例代码
<!-- 定义SQL片段 -->
<sql id="carCols">id,car_num carNum,brand,guide_price guidePrice,produce_time produceTime,car_type carType
</sql><!-- 使用SQL片段 -->
<select id="selectAllRetMap" resultType="map">select <include refid="carCols"/> from t_car
</select><select id="selectByIdRetMap" resultType="map">select <include refid="carCols"/> from t_car where id = #{id}
</select>
使用建议
  1. 将常用的列名、条件等提取为SQL片段
  2. 保持SQL片段的独立性
  3. 注意SQL片段的命名规范

12.9 动态SQL最佳实践

  1. 参数处理

    • 使用@Param注解明确参数名
    • 做好空值处理
    • 注意参数类型转换
  2. 性能优化

    • 避免过度使用动态SQL
    • 注意SQL注入风险
    • 考虑使用缓存
  3. 代码维护

    • 保持SQL语句的可读性
    • 适当使用SQL片段
    • 添加必要的注释
  4. 错误处理

    • 做好异常处理
    • 添加日志记录
    • 考虑回滚机制

13. MyBatis高级映射与延迟加载指南

13.1 多对一映射

13.0 概念与实现方式

多对一映射指多个实体对象关联到同一个实体对象的情况(如多个学生属于同一个班级)。

三种实现方式

  1. 级联属性映射(单SQL)2. association标签(单SQL)3. 分步查询(双SQL,推荐)
13.1.1 级联属性映射

实现步骤:

  1. 在Student类中添加Clazz属性:
public class Student {private Integer sid;        // 学生IDprivate String sname;       // 学生姓名private Clazz clazz;        // 关联的班级对象// getter和setter方法public Clazz getClazz() {return clazz;}public void setClazz(Clazz clazz) {this.clazz = clazz;}
}
  2. 在StudentMapper.xml中配置:
<!-- 定义结果映射 -->
<resultMap id="studentResultMap" type="Student"><!-- 主键映射 --><id property="sid" column="sid"/><!-- 普通属性映射 --><result property="sname" column="sname"/><!-- 级联属性映射 --><result property="clazz.cid" column="cid"/><result property="clazz.cname" column="cname"/>
</resultMap><!-- 查询语句 -->
<select id="selectBySid" resultMap="studentResultMap">select s.*, c.* from t_student s join t_clazz c on s.cid = c.cid where sid = #{sid}
</select>

特点:

  • 使用一条SQL语句完成查询
  • 通过级联属性映射(clazz.cid)实现关联
  • 配置简单,但不够灵活
  • 适合简单的关联查询场景

性能考虑:

  • 优点:减少数据库连接次数,提高查询效率
  • 缺点:当关联表数据量大时,可能会影响查询性能
13.1.2 association标签

使用association标签可以更清晰地表达对象之间的关联关系:

<resultMap id="studentResultMap" type="Student"><id property="sid" column="sid"/><result property="sname" column="sname"/><!-- 使用association标签映射关联对象 --><association property="clazz" javaType="Clazz"><id property="cid" column="cid"/><result property="cname" column="cname"/></association>
</resultMap>

特点:

  • 使用一条SQL语句完成查询
  • 通过association标签实现关联
  • 配置更清晰,易于理解
  • 支持更复杂的映射关系
  • 适合需要展示关联对象详细信息的场景

最佳实践:

  1. 使用有意义的别名,提高SQL可读性2. 明确指定需要查询的字段,避免使用select *3. 合理使用索引,提高查询效率
13.1.3 分步查询(推荐)

分步查询是最常用的方式,它通过两条SQL语句完成查询:

优点:

  1. 代码复用性增强:关联查询的SQL可以被其他查询复用2. 支持延迟加载:可以按需加载关联数据,提高性能3. 更好的可维护性:每个查询职责单一4. 更灵活的控制:可以独立优化每个查询

实现步骤:

  1. 修改StudentMapper.xml:
<resultMap id="studentResultMap" type="Student"><id property="sid" column="sid"/><result property="sname" column="sname"/><!-- 使用association进行分步查询 --><association property="clazz"select="com.powernode.mybatis.mapper.ClazzMapper.selectByCid"column="cid"/>
</resultMap><select id="selectBySid" resultMap="studentResultMap">select s.* from t_student s where sid = #{sid}
</select>
  2. 在ClazzMapper接口中添加方法:
public interface ClazzMapper {/*** 根据班级ID查询班级信息* @param cid 班级ID* @return 班级对象*/Clazz selectByCid(Integer cid);
}
  3. 在ClazzMapper.xml中配置:
<select id="selectByCid" resultType="Clazz">select * from t_clazz where cid = #{cid}
</select>

性能优化建议:

  1. 为关联字段建立索引2. 合理使用缓存3. 控制查询的字段数量4. 考虑使用批量查询优化性能

13.2 多对一延迟加载

延迟加载(Lazy Loading)是指只有在真正使用到关联数据时才会执行查询,这样可以提高系统性能。

13.2.1 局部延迟加载

在association标签中添加fetchType=“lazy”:

<association property="clazz"select="com.powernode.mybatis.mapper.ClazzMapper.selectByCid"column="cid"fetchType="lazy"/>

使用场景:

@Test
public void testSelectBySid(){StudentMapper mapper = SqlSessionUtil.openSession().getMapper(StudentMapper.class);Student student = mapper.selectBySid(1);// 此时只查询学生信息,不查询班级信息String sname = student.getSname();System.out.println("学生姓名:" + sname);// 当访问班级信息时,才会执行班级查询String cname = student.getClazz().getCname();System.out.println("班级名称:" + cname);
}

延迟加载的注意事项:

  1. 确保SqlSession在使用完之前不要关闭2. 注意N+1查询问题3. 考虑使用批量加载优化性能4. 合理设置延迟加载的触发条件
13.2.2 全局延迟加载

在mybatis-config.xml中配置全局延迟加载:

<settings><!-- 开启全局延迟加载 --><setting name="lazyLoadingEnabled" value="true"/><!-- 设置延迟加载的触发方法 --><setting name="lazyLoadTriggerMethods" value="equals,clone,hashCode,toString"/>
</settings>

如果某个SQL不想使用延迟加载,可以设置fetchType=“eager”:

<association property="clazz"select="com.powernode.mybatis.mapper.ClazzMapper.selectByCid"column="cid"fetchType="eager"/>

全局延迟加载的配置选项:

  1. lazyLoadingEnabled:是否开启延迟加载2. aggressiveLazyLoading:是否启用积极的延迟加载3. lazyLoadTriggerMethods:指定触发延迟加载的方法

13.3 一对多映射

一对多映射是指一个实体对象包含多个其他实体对象的情况。例如:一个班级包含多个学生。

13.3.1 实现方式
  1. 在Clazz类中添加List<Student>属性:
public class Clazz {private Integer cid;            // 班级IDprivate String cname;           // 班级名称private List<Student> stus;     // 学生列表// getter和setter方法public List<Student> getStus() {return stus;}public void setStus(List<Student> stus) {this.stus = stus;}
}
  2. 使用collection标签实现:
<resultMap id="clazzResultMap" type="Clazz"><id property="cid" column="cid"/><result property="cname" column="cname"/><!-- 使用collection映射集合属性 --><collection property="stus" ofType="Student"><id property="sid" column="sid"/><result property="sname" column="sname"/></collection>
</resultMap><select id="selectClazzAndStusByCid" resultMap="clazzResultMap">select c.*, s.* from t_clazz c join t_student s on c.cid = s.cid where c.cid = #{cid}
</select>

一对多映射的性能考虑:

  1. 数据量大的情况下,建议使用分步查询2. 合理使用索引提高查询效率3. 考虑使用缓存减少数据库访问4. 控制返回的数据量
13.3.2 分步查询
  1. 修改ClazzMapper.xml:
<resultMap id="clazzResultMap" type="Clazz"><id property="cid" column="cid"/><result property="cname" column="cname"/><!-- 使用collection进行分步查询 --><collection property="stus"select="com.powernode.mybatis.mapper.StudentMapper.selectByCid"column="cid"/>
</resultMap><select id="selectClazzAndStusByCid" resultMap="clazzResultMap">select * from t_clazz c where c.cid = #{cid}
</select>
  2. 在StudentMapper接口中添加方法:
/**
* 根据班级ID查询学生列表
* @param cid 班级ID
* @return 学生列表
*/
List<Student> selectByCid(Integer cid);
  3. 在StudentMapper.xml中配置:
<select id="selectByCid" resultType="Student">select * from t_student where cid = #{cid}
</select>

分步查询的优化建议:

  1. 使用批量查询代替循环查询2. 合理设置缓存策略3. 优化SQL语句,使用索引4. 控制返回的字段数量

13.4 一对多延迟加载

一对多延迟加载的实现方式与多对一相同:

  1. 局部延迟加载:在collection标签中添加fetchType="lazy"2. 全局延迟加载:在mybatis-config.xml中配置lazyLoadingEnabled=true3. 如果开启全局延迟加载后,某个SQL不想使用延迟加载,可以设置fetchType="eager"

使用建议:

  1. 对于频繁访问的关联数据,建议使用立即加载(eager)2. 对于不常访问的关联数据,建议使用延迟加载(lazy)3. 在开发阶段可以通过日志查看SQL执行情况,优化加载策略4. 注意处理延迟加载可能带来的性能问题

性能优化技巧:

  1. 使用批量查询代替单条查询2. 合理设置缓存策略3. 优化数据库索引4. 控制返回的数据量5. 使用合适的连接池配置

常见问题及解决方案:

  1. N+1查询问题:使用批量查询或缓存解决2. 性能问题:优化SQL语句,使用索引3. 内存问题:控制返回的数据量4. 事务问题:确保在事务范围内使用延迟加载

14. MyBatis缓存

14.1 缓存概述

什么是缓存?

缓存(cache)是一种临时存储机制,用于存储频繁访问的数据,以减少对原始数据源的访问次数,从而提高系统性能。

MyBatis缓存的作用
  • 减少数据库IO操作
  • 提高查询效率
  • 减轻数据库压力
  • 提升系统响应速度
MyBatis缓存机制

MyBatis的缓存机制:将select语句的查询结果存储到缓存(内存)中,当再次执行相同的select语句时,直接从缓存中获取数据,不再查询数据库。这样既减少了IO操作,又避免了重复执行复杂的查找算法,从而显著提升性能。

MyBatis缓存分类
  1. 一级缓存(本地缓存)

    • 作用域:SqlSession级别
    • 存储位置:SqlSession内部
    • 特点:默认开启,无需配置
  2. 二级缓存(全局缓存)

    • 作用域:SqlSessionFactory级别
    • 存储位置:SqlSessionFactory内部
    • 特点:需要手动配置开启
  3. 第三方缓存

    • 可集成框架:EhCache、Memcache、Redis等
    • 特点:提供更强大的缓存功能
    • 适用场景:分布式系统、高并发场景

重要说明:

  • 缓存只针对DQL语句,即只对select查询语句生效
  • 增删改操作会使缓存失效
  • 缓存的使用需要权衡内存占用和性能提升

14.2 一级缓存

基本概念

一级缓存是MyBatis默认开启的缓存机制,它存在于SqlSession的生命周期中。

工作原理
  • 使用同一个SqlSession对象执行相同的SQL语句时,会直接使用缓存数据
  • 缓存数据存储在SqlSession的HashMap中
  • 当SqlSession关闭时,缓存数据会被清空
测试代码示例
@Test
public void testSelectById() throws Exception {// 获取SqlSessionFactorySqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis-config.xml"));// 使用同一个SqlSession进行两次查询SqlSession sqlSession1 = sqlSessionFactory.openSession();CarMapper mapper1 = sqlSession1.getMapper(CarMapper.class);Car car1 = mapper1.selectById(83L);System.out.println(car1);CarMapper mapper2 = sqlSession1.getMapper(CarMapper.class);Car car2 = mapper2.selectById(83L);System.out.println(car2);// 使用不同的SqlSession进行查询SqlSession sqlSession2 = sqlSessionFactory.openSession();CarMapper mapper3 = sqlSession2.getMapper(CarMapper.class);Car car3 = mapper3.selectById(83L);System.out.println(car3);CarMapper mapper4 = sqlSession2.getMapper(CarMapper.class);Car car4 = mapper4.selectById(83L);System.out.println(car4);
}
一级缓存失效的情况
  1. 使用不同的SqlSession对象

    • 每个SqlSession都有自己的一级缓存
    • 不同SqlSession的缓存互不影响
  2. 查询条件发生变化

    • SQL语句不同
    • 参数值不同
  3. 手动清空缓存

    sqlSession.clearCache();
    
  4. 执行增删改操作

    • 任何insert、delete、update操作都会使一级缓存失效
    • 无论操作的是哪张表,都会导致缓存失效
使用建议
  1. 对于频繁查询且数据变化不大的场景,建议使用一级缓存
  2. 对于数据实时性要求高的场景,建议关闭一级缓存
  3. 在事务中,合理使用一级缓存可以提高性能

14.3 二级缓存

基本概念

二级缓存是SqlSessionFactory级别的缓存,多个SqlSession可以共享二级缓存。

使用条件
  1. 全局配置开启缓存(默认已开启):

    <setting name="cacheEnabled" value="true"/>
    
  2. 在Mapper.xml文件中添加配置:

    <cache/>
    
  3. 实体类必须实现Serializable接口

    public class Car implements Serializable {// 实现序列化接口
    }
    
  4. SqlSession关闭或提交后,一级缓存数据才会写入二级缓存

二级缓存失效

当两次查询之间出现任何增删改操作时:

  • 二级缓存会失效
  • 一级缓存也会同时失效
  • 需要重新查询数据库
二级缓存配置详解
<cache eviction="LRU" flushInterval="60000" readOnly="true" size="1024"/>
配置项说明
  1. eviction:缓存淘汰策略

    • LRU(默认):最近最少使用,优先淘汰间隔时间内使用频率最低的对象
    • FIFO:先进先出,先进入二级缓存的对象最先被淘汰
    • SOFT:软引用,根据JVM垃圾回收算法淘汰对象
    • WEAK:弱引用,根据JVM垃圾回收算法淘汰对象
  2. flushInterval:刷新间隔(毫秒)

    • 未设置时,缓存不会自动刷新,除非执行增删改操作
    • 设置后,会定期刷新缓存
  3. readOnly:

    • true:返回共享对象,性能好但可能存在线程安全问题
    • false:返回对象副本,性能一般但安全
  4. size:二级缓存最大存储对象数量(默认1024)

使用建议
  1. 二级缓存适合:

    • 查询频率高
    • 数据更新频率低
    • 数据量不是特别大
    • 对实时性要求不高的场景
  2. 二级缓存不适合:

    • 数据频繁更新
    • 对数据实时性要求高
    • 数据量特别大
    • 多表关联查询复杂

14.4 MyBatis集成EhCache

为什么使用EhCache?
  • 提供更强大的缓存功能
  • 支持分布式缓存
  • 提供更灵活的配置选项
  • 性能优于MyBatis默认的二级缓存
集成步骤
  1. 添加依赖:
<dependency><groupId>org.mybatis.caches</groupId><artifactId>mybatis-ehcache</artifactId><version>1.2.2</version>
</dependency>
  1. 创建ehcache.xml配置文件:
<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd"updateCheck="false"><!-- 磁盘存储路径 --><diskStore path="e:/ehcache"/><!-- 默认缓存策略 --><defaultCache eternal="false" maxElementsInMemory="1000" overflowToDisk="false" diskPersistent="false"timeToIdleSeconds="0" timeToLiveSeconds="600" memoryStoreEvictionPolicy="LRU"/>
</ehcache>
  1. 修改Mapper.xml中的缓存配置:
<cache type="org.mybatis.caches.ehcache.EhcacheCache"/>
EhCache配置详解
  1. diskStore:磁盘存储配置

    • path:缓存文件存储路径
    • 作用:当内存不足时,将数据存储到磁盘
  2. defaultCache:默认缓存策略

    • eternal:是否永久有效

      • true:缓存永久有效
      • false:根据timeToIdleSeconds和timeToLiveSeconds判断有效期
    • maxElementsInMemory:内存中最大缓存对象数

    • overflowToDisk:是否缓存到磁盘

      • true:内存不足时缓存到磁盘
      • false:内存不足时抛出异常
    • diskPersistent:是否持久化到磁盘

      • true:重启后恢复缓存
      • false:重启后清空缓存
    • timeToIdleSeconds:对象空闲时间(秒)

      • 0:表示一直有效

      • 0:表示空闲指定时间后失效

    • timeToLiveSeconds:对象存活时间(秒)

      • 0:表示一直有效

      • 0:表示创建后指定时间失效

    • memoryStoreEvictionPolicy:缓存清理策略

      • FIFO:先进先出
      • LFU:最少使用
      • LRU:最近最少使用(默认)
使用建议
  1. 根据实际需求调整缓存配置
  2. 合理设置缓存大小和过期时间
  3. 注意监控缓存命中率和内存使用情况
  4. 在分布式环境中注意缓存同步问题
常见问题解决
  1. 缓存穿透:查询不存在的数据

    • 解决方案:缓存空对象或使用布隆过滤器
  2. 缓存雪崩:大量缓存同时失效

    • 解决方案:设置不同的过期时间
  3. 缓存击穿:热点数据失效

    • 解决方案:使用互斥锁或永不过期

相关文章:

mybatis的第五天学习笔记

12. 动态SQL 12.1 动态SQL概述 新增内容&#xff1a; 动态SQL执行流程 MyBatis如何解析动态SQLSQL语句构建过程参数绑定机制 新增示例 // 动态条件查询接口示例 List<User> searchUsers(Param("name") String name,Param("age") Integer age,Para…...

LeetCode 941 有效的山脉数组

算法探索&#xff1a;如何精准判断有效山脉数组 在计算机科学领域&#xff0c;算法和数据结构堪称基石&#xff0c;它们不仅是解决复杂问题的有力工具&#xff0c;更是衡量程序员技术水平的重要指标。数组作为最基础、应用最广泛的数据结构之一&#xff0c;围绕它衍生出了大量…...

java设计模式-单例模式

单例模式 1、饿汉式(静态常量) Slf4j public class SingletonTest01 {public static void main(String[] args) {Singleton singleton Singleton.getInstance();Singleton singleton2 Singleton.getInstance();log.info("比对结果&#xff1a;{}",singletonsingl…...

对抗Prompt工程:构建AI安全护栏的攻防实践

大语言模型的开放性与自然语言交互特性使其面临前所未有的Prompt工程攻击威胁。本文通过分析2021-2023年间157个真实越狱案例&#xff0c;揭示语义混淆、上下文劫持、多模态组合三重攻击路径的技术原理&#xff0c;提出融合动态意图拓扑分析&#xff08;DITA&#xff09;、对抗…...

CentOS 环境下 MySQL 数据库全部备份的操作指南

最近阿里云个人服务到期&#xff0c;因为是很久之前买的测试机器&#xff0c;配置较低&#xff0c;上面运行的有技术博客 和以往的测试项目&#xff0c;所以准备放弃掉。 需要备份下上面的表结构和数据、以及代码仓库。 下面是一个完整的 CentOS 环境下 MySQL 数据库全部备份…...

回溯算法补充leetcode

1. 组合 leetcode题目链接&#xff1a;77. 组合 给定两个整数 n 和 k&#xff0c;返回范围 [1, n] 中所有可能的 k 个数的组合。 你可以按 任何顺序 返回答案。 示例 1&#xff1a; 输入&#xff1a;n 4, k 2 输出&#xff1a; [[2,4],[3,4],[2,3],[1,2],[1,3],[1,4], ] 示…...

利用 AI 实现雷池 WAF 自动化运维

欢迎加入雷池社区&#xff1a;雷池 WAF | 下一代 Web 应用防火墙 | 免费使用 已经升级到 8.4.0 的兄弟们应该会发现雷池又多了一些 AI 能力&#xff0c;8.4.0 更新公告。 感谢 Web2GPT 为雷池提供的 AI 能力支持。 主要变化 右下角多了一个 AI 小助手 按钮右上角多了一个 连…...

【嵌入式面试】

1、如果中断函数中有耗时较长的内容&#xff0c;会导致以下问题&#xff0c;如何解决&#xff1f; 对系统实时性的影响 阻塞低优先级中断&#xff1a;中断函数执行时间过长&#xff0c;会阻塞其他低优先级中断的响应。例如&#xff0c;如果一个高优先级中断处理程序中包含耗时…...

【Hadoop入门】Hadoop生态之HDFS

1 HDFS核心设计原理 HDFS&#xff08;Hadoop Distributed File System&#xff09;是专为大规模数据存储设计的分布式文件系统&#xff0c;其核心设计基于以下原则&#xff1a; 数据分块与分布式存储&#xff1a; 分块机制&#xff1a;文件被切分为固定大小的数据块&#xff08…...

试剂SYBR 14核酸染料在染色时的操作步骤(说明)

化学试剂的基本内容||试剂参数 ---中文名&#xff1a;SYBR 14核酸染料 ---英文名&#xff1a;SYBR 14 Nucleic Acid Stain ---浓度&#xff1a;通常以5mM的DMSO储存液形式提供。 ---吸收波长&#xff1a;488nm ---发射波长&#xff1a;518nm ---出厂商&#xff1a;西安强…...

Spring Boot 国际化配置项详解

Spring Boot 国际化配置项详解 1. 核心配置项分类 将配置项分为以下类别&#xff0c;便于快速定位&#xff1a; 1.1 消息源配置&#xff08;MessageSource 相关&#xff09; 控制属性文件的加载、编码、缓存等行为。 配置项作用默认值示例说明spring.messages.basename指定属…...

Python之禅:深入理解Python设计哲学

Python之禅(The Zen of Python)是Python语言的核心设计哲学&#xff0c;由Python创始人Guido van Rossum和Tim Peters共同制定。理解Python之禅不仅能帮助我们写出更"Pythonic"的代码&#xff0c;还能深入把握Python语言的设计理念。 Python之禅的由来 Python之禅最…...

Rancher 全面介绍

目录 Rancher 全面介绍1. **Rancher 的定义与核心功能**2. **Rancher 的应用场景**3. **Rancher 的生态系统**4. **Rancher 的优势**5. **总结** Rancher 全面介绍 1. Rancher 的定义与核心功能 Rancher 是一个开源的企业级多集群 Kubernetes 管理平台&#xff0c;旨在简化容…...

Docker常用命令

镜像命令 搜索镜像 docker search nginx 拉取镜像 docker pull nginx&#xff0c;默认拉取最新镜像 docker pull nginx:1.25.3&#xff0c;拉取指定版本 查看镜像 docker images 删除镜像 docker rmi nginx:1.25.3 docker rmi -f $(docker images -aq)&#xff0c;删除全…...

项目中如何防止超卖

什么是超卖&#xff1f;假如只剩下一个库存&#xff0c;却被多个订单买到了&#xff0c;简单理解就是库存不够了还能正常下单。 方案1&#xff1a;数据库行级锁 1. 实体类 Data TableName("product") public class Product {TableId(type IdType.AUTO)private Lon…...

龙虎榜——20250408

行情如下 根据2025年4月8日的龙虎榜的行业分析如下&#xff1a; 一、农业种植与乡村振兴 • 政策催化&#xff1a;推进种业自主创新、农机装备升级等目标&#xff0c;叠加中美关税反制逻辑。 • 市场表现&#xff1a; • 农业种植&#xff1a;种子类企业因国产替代预期受资…...

快速上手Vue3国际化 (i18n)

文章目录 一、背景介绍二、页面效果三、使用步骤四、代码1.src/App.vue2.src/main.js3.src/locales/index.js4.src/views/login/_request.js5.src/locales/en.json6.src/locales/zh.json7.SystemParam.vue8.I18NController.java9.DataServiceConfigValue.java10.ConfigValue.ja…...

Mistral OCR:重新定义文档理解的下一代 OCR 技术

引言 在数字化时代,文档处理和理解是企业、科研机构以及个人工作流程中的重要环节。然而,传统的光学字符识别(OCR)技术往往难以应对复杂文档中的多语言、多模态内容。近日,法国 AI 明星创企 Mistral AI 推出了一款名为 Mistral OCR 的光学字符识别 API,以其卓越的性能和…...

前端面试核心知识点整理:从 JavaScript 到 Vue 全解析

一、JavaScript 异步编程核心:Promise 与 async/await 1. Promise 深度解析 定义:Promise 是处理异步操作的对象,代表一个异步操作的最终状态(成功 / 失败)。三种状态: pending(进行中):初始状态,异步操作未完成。fulfilled(已成功):异步操作成功,调用 resolve …...

npm fund 命令的作用

运行别人的项目遇到这个问题&#xff1a; npm fund 命令的作用 npm fund 是 npm 提供的命令&#xff0c;用于显示项目依赖中哪些包需要资金支持。这些信息来自包的 package.json 中定义的 funding 字段&#xff0c;目的是帮助开发者了解如何支持开源维护者。 典型场景示例 假…...

LeetCode344反转字符串

思路&#xff1a; 交换即可 void reverseString(char* s, int sSize) {int jsSize-1;for(int i0;i<sSize/2;i){int tmps[i];s[i]s[j];s[j]tmp;j--;} }...

[Python] 企业内部应用接入钉钉登录,端内免登录+浏览器授权登录

[Python] 为企业网站应用接入钉钉鉴权&#xff0c;实现钉钉客户端内自动免登授权&#xff0c;浏览器中手动钉钉授权登录两种逻辑。 操作步骤 企业内部获得 开发者权限&#xff0c;没有的话先申请。 访问 钉钉开放平台-应用开发 创建一个 企业内部应用-钉钉应用。 打开应用…...

设计模式-单例设计模式

目录 什么是单例设计模式&#xff1f; 为什么要使用单例模式&#xff1f; 资源方面 数据一致方面 系统性能方面 代码维护方面 如何设计单例类&#xff1f; 在说模式之前&#xff0c;我们需要先知道怎么设计才可以让一个类只能有一个实例化对象呢&#xff1f; 饿汉模式…...

Nextjs15 实战 - React Notes CURD 实现

本专栏内容均可在Github&#xff1a;notes_04 找到 完整项目使用技术栈&#xff1a; Nextjs15 MySQL Redis Auth Prisma i18n strapi Docker vercel 一、本节目标 本篇我们来实现右侧笔记CURD部分。 一、效果 当点击 New 按钮的时候进入编辑界面&#xff1a; 当点击…...

【KWDB 创作者计划】架构设计与AIoT场景实践

产品定位与核心价值主张 架构设计与技术实现 分布式架构设计 多模存储引擎实现 云边端协同机制 核心技术创新解析 就地计算技术 自适应时序引擎 混合事务处理 性能优化技术体系 高效存储机制 查询加速策略 资源管理与隔离 行业解决方案与典型应用 工业物联网平台…...

DeepSeek底层揭秘——《推理时Scaling方法》技术对比浅析

4月初&#xff0c;DeepSeek 提交到 arXiv 上的最新论文正在 AI 社区逐渐升温。 笔者尝试对比了“关于推理时Scaling”与现有技术&#xff0c;粗浅分析如下&#xff1a; 与LoRA的对比 区别&#xff1a; 应用场景&#xff1a;LoRA是一种参数高效微调方法&#xff0c;主要用于在…...

Spring MVC与Spring Boot文件上传配置差异对比及文件上传关键类详细说明与对比

一、Spring MVC与Spring Boot文件上传配置差异对比 1. 配置方式差异 框架配置方式依赖管理自动配置Spring MVC需手动配置MultipartResolver&#xff08;如StandardServletMultipartResolver&#xff09;需自行引入commons-fileupload等依赖无&#xff0c;默认不启用文件上传支…...

Linux网络配置与测试

目录 一.与网络配置相关的命令 1.1ifconfig命令 1.1.1作用 1.1.2网络接口的信息 接口信息的组成 1.1.3显示所有网卡包括没有启动的网卡 1.1.4查看指定网络接口 1.1.5开启或关闭网卡 1.1.6设置临时虚拟网卡 1.1.7网络通讯情况 ​编辑 1.1.8临时修改网卡属性 1.2hos…...

游戏赛季和数据处理

问题 游戏从无赛季到赛季机制会涉及哪些问题&#xff1a; 如何改动&#xff0c;增加赛季机制&#xff0c;涉及要修改的代码量最少如何改动&#xff0c;账号、角色部分数据继承问题&#xff0c;涉及要修改的代码量最少账号下角色的永久服共享或是永久服独立&#xff0c;需要做…...

京东店铺托管7*16小时全时护航

内容概要 京东店铺托管服务的*716小时全时护航模式&#xff0c;相当于给商家配了个全年无休的"运营管家"。专业团队每天从早7点到晚11点实时盯着运营数据和商品排名&#xff0c;连半夜流量波动都能通过智能系统秒级预警。这种全天候服务可不是单纯拼人力——系统自动…...

HTTP的Keep-Alive是什么?TCP 的 Keepalive 和 HTTP 的 Keep-Alive 是一个东西吗?

HTTP的Keep-Alive&#xff1a; HTTP Keep-Alive 是一种机制&#xff0c;允许客户端和服务器在单个 TCP 连接 上发送多个 HTTP 请求 和 响应&#xff0c;而不是每次请求和响应后都关闭连接。它的主要目的是提高性能&#xff0c;减少连接的开销&#xff0c;优化通信效率。 工作…...

使用scoop一键下载jdk和实现版本切换

安装 在 PowerShell 中输入下面内容&#xff0c;保证允许本地脚本的执行&#xff1a; set-executionpolicy remotesigned -scope currentuser然后执行下面的命令安装 Scoop&#xff1a; iwr -useb get.scoop.sh | iex国内用户可以使用镜像源安装&#xff1a;powershell iwr -us…...

PPIO × UI-TARS:用自然语言操控电脑,AI Agent 的极致体验

Manus的爆火预示着AI 正在从单纯的文本生成和图像识别迈向更复杂的交互场景。字节跳动近期推出的开源项目 UI-TARS Desktop 为我们展示了一种全新的可能性&#xff1a;能够通过自然语言理解和处理来控制计算机界面。这款工具代表了人工智能与人机交互领域的重大突破&#xff0c…...

PG:incorrect prev-link

目录 WAL日志中"incorrect prev-link"错误解决方案错误原因分析解决步骤典型修复案例 WAL日志中"incorrect prev-link"错误解决方案 错误原因分析 WAL日志的prev-link字段用于确保日志记录的连续性。当出现incorrect prev-link 2/754ECB0 at 2/8000028错…...

SQL Server 数据库邮件配置失败:SMTP 连接与权限问题

问题现象&#xff1a; 配置数据库邮件时&#xff0c;发送测试邮件失败&#xff0c;提示 “邮件无法发送到 SMTP 服务器&#xff0c;操作超时”&#xff08;错误 14661&#xff09;或 “服务器拒绝发件人地址”&#xff08;错误 15009&#xff09;。 快速诊断 检查数据库邮件配置…...

深入浅出动态规划:从基础到蓝桥杯实战(Java版)

引言&#xff1a;为什么你需要掌握动态规划&#xff1f; 动态规划&#xff08;DP&#xff09;是算法竞赛和面试中的常客&#xff0c;不仅能大幅提升解题效率&#xff08;时间复杂度通常为O(n)或O(n)&#xff09;[4]&#xff0c;更是解决复杂优化问题的利器。统计显示&#xff…...

获取cookie的chrome插件:Get cookies.txt LOCALLY

接上一篇&#xff0c;在下载视频的时候需要网站的cookie&#xff0c;下面介绍一款可以获取网站cookie的chrome插件 https://chromewebstore.google.com/detail/get-cookiestxt-locally/cclelndahbckbenkjhflpdbgdldlbecc?utm_sourceitem-share-cb 备注需要科学上网 【使用方…...

opencv无法设置禁用RGB转换问题

树莓派连接摄像头,摄像头输出格式为YUYV(YUV422)。 通过执行 v4l2-ctl --list-formats --device/dev/video0 可以看的具体的摄像头的数据格式。 使用opencv获取视频流&#xff0c;通过cap.set(cv2.CAP_PROP_CONVERT_RGB, 0)设置禁用自动转换RGB格式&#xff0c;但是打印输出…...

Ansible:roles角色

文章目录 Roles角色Ansible Roles目录编排Roles各目录作用创建 roleplaybook调用角色调用角色方法1&#xff1a;调用角色方法2&#xff1a;调用角色方法3&#xff1a; roles 中 tags 使用实战案例 Roles角色 角色是ansible自1.2版本引入的新特性&#xff0c;用于层次性、结构化…...

SAP系统采购信息记录失效

问题&#xff1a;采购信息记录失效 现象&#xff1a;最初主数据导入完成之后&#xff0c;单元测试的时采购信息记录是有效的&#xff0c;中间经过配置的变化&#xff0c;集成测试初期发现采购信息记录全部失效。 原因&#xff1a; 单元测试时发现采购订单里面的条件类型…...

JavaWeb 课堂笔记 —— 04 Ajax

本系列为笔者学习JavaWeb的课堂笔记&#xff0c;视频资源为B站黑马程序员出品的《黑马程序员JavaWeb开发教程&#xff0c;实现javaweb企业开发全流程&#xff08;涵盖SpringMyBatisSpringMVCSpringBoot等&#xff09;》&#xff0c;章节分布参考视频教程&#xff0c;为同样学习…...

Pandas 库

Pandas 是一个开源的数据分析和数据处理库&#xff0c;它是基于 Python 编程语言的。 Pandas 提供了易于使用的数据结构和数据分析工具&#xff0c;特别适用于处理结构化数据&#xff0c;如表格型数据 Pandas 是数据科学和分析领域中常用的工具之一&#xff0c;它使得用户能够…...

4.8学习总结

完成摆动序列的算法题&#xff08;比较难&#xff0c;想不出方法&#xff09; 学习了HashMap,TreeMap 的源码&#xff08;看完一遍对其理解没有太清楚&#xff0c;还需再多刷几遍理解源码及其底层逻辑的概念&#xff09; 学习了可变参数和Collections工具类...

C语言之九九乘法表

一、代码展示 二、运行结果 三、代码分析 首先->是外层循环是小于等于9的 然后->是内层循环是小于等于外层循环的 最后->就是\n让九九乘法表的格式更加美观(当然 电脑不同 有可能%2d 也有可能%3d) 四、与以下素数题目逻辑相似 五、运行结果...

【Linux操作系统】:信号

Linux操作系统下的信号 一、引言 首先我们可以简单理解一下信号的概念&#xff0c;信号&#xff0c;顾名思义&#xff0c;就是我们操作系统发送给进程的消息。举个简单的例子&#xff0c;我们在写C/C程序的时候&#xff0c;当执行a / 0类似的操作的时候&#xff0c;程序直接就挂…...

skynet.call使用详解

目录 skynet.call 详细解析1. 函数签名与参数2. 内部实现机制3. 会话ID与协程调度4. 超时与错误处理5. 返回值处理6. 协议类型的影响7. skynet.call vs skynet.send8. 示例代码分析9. 最佳实践10. 总结 skynet.call 详细解析 1. 函数签名与参数 函数签名&#xff1a; skynet…...

uniapp 打包 H5 向 打包的APP 使用 @dcloudio/uni-webview-js 传值

1.安装 dcloudio/uni-webview-js npm install dcloudio/uni-webview-js -save 这个模块的 uni. 会与H5的uniapp的 uni. 冲突,所以需要改下名称,一共需要改3处 2.引入并使用 import uniWeb from dcloudio/uni-webview-js;uniWeb.postMessage({data: {action: message,content…...

c语言 文件操作

c语言 文件操作 one 打开/usr/dev.txt文件&#xff0c;在第1行 覆盖写入 "MAC1q23456789" #include <fcntl.h> #include <unistd.h> #include <string.h> int main() { const char *line_1 "MAC1q23456789\n"; // 要写入的内容…...

企业电子招投标采购系统——功能模块功能描述+数字化采购管理 采购招投标

​功能描述 1、门户管理&#xff1a;所有用户可在门户页面查看所有的公告信息及相关的通知信息。主要板块包含&#xff1a;招标公告、非招标公告、系统通知、政策法规。 2、立项管理&#xff1a;企业用户可对需要采购的项目进行立项申请&#xff0c;并提交审批&#xff0c;查看…...

Python 序列构成的数组(序列的增量赋值)

序列的增量赋值 增量赋值运算符 和 * 的表现取决于它们的第一个操作对象。简单起 见&#xff0c;我们把讨论集中在增量加法&#xff08;&#xff09;上&#xff0c;但是这些概念对 * 和其他 增量运算符来说都是一样的。 背后的特殊方法是 iadd &#xff08;用于“就地加法”&…...