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

MyBatis 的一级、二级缓存机制

目录标题

  • 缓存
    • 什么是缓存
    • 为什么使用缓存
    • 什么样的数据能使用缓存,什么样的数据不能使用
      • 适用于缓存
      • 不适用于缓存
    • MyBatis 一级缓存、二级缓存关系
  • 1. 一级缓存
    • 1.1 什么是一级缓存mybatis
    • 1.2 一级缓存配置
    • 1.3 什么情况下会命中一级缓存
      • mybatis清除一级缓存的几种方法
    • 1.4 内部结构
      • PerpetualCache
    • 1.5 clear() == map.clear()
      • insert/delete/update 方法, 清空 localCache
    • 1.6 Mybatis的一级缓存时序图
    • 1.7 一级缓存实验
      • 一级缓存同一个会话共享数据
      • 同一个会话如果有更新操作则缓存清除
      • 一级缓存在多会话中会导致脏数据
      • 解决方式:在配置一级缓存作用范围的时候将其设置为 STATEMENT,那么缓存仅对当前执行的语句有效,当语句执行完毕后,缓存就会被清空。
  • 2. 二级缓存
    • 2.2 二级缓存工作流程
    • 2.2 二级缓存配置
      • 二级缓存何时存入
      • 二级缓存如何清空
    • 2.3 二级缓存实验
      • 测试二级缓存与 SqlSession 无关
      • 测试执行 commit(),二级缓存数据清空
      • 多表操作一定不能使用缓存
    • useCache 和 flushCache

缓存

什么是缓存

缓存是存在于内存中的临时数据。

为什么使用缓存

使用缓存减少和数据库的交互次数,提高执行效率。(因为查询数据库是一件很费时很费效率的事,还涉及一些硬盘等io操作,而缓存是存在内存中的,读取都很快,而且效率高)

什么样的数据能使用缓存,什么样的数据不能使用

适用于缓存

经常查询并且不经常改变的;
数据的正确与否对最终结果影响不大的;

不适用于缓存

经常改变的数据;
数据的正确与否对最终结果影响很大的;
例如:商品的库存,银行的汇率,股市的牌价;

MyBatis 一级缓存、二级缓存关系

在这里插入图片描述
一级缓存是 SqlSession 级别的缓存。在操作数据库时需要构造 SqlSession 对象,在对象中有一个数据结构(HashMap)用于存储缓存数据。不同的是 SqlSession 之间的缓存数据区(HashMap)是互相不影响。
二级缓存是 Mapper 级别的缓存,多个 SqlSession 去操作同一个 Mapper 的 sql 语句,多个 SqlSession 可以共用二级缓存,二级缓存是跨 SqlSession 的。

1. 一级缓存

1.1 什么是一级缓存mybatis

默认情况下只会开启一级缓存,也就是局部的 session 会话缓存。
每一个 session 会话都会有各自的缓存,是局部的。

1.2 一级缓存配置

<setting name="localCacheScope" value="SESSION"/>

在 MyBatis 的配置文件中添加上面语句,就可以使用一级缓存。共有两个选项,SESSION 或者 STATEMENT。
默认是 SESSION 级别,即在一个 MyBatis 会话中执行的所有语句,都会共享这一个缓存。
一种是 STATEMENT 级别,可以理解为缓存只对当前执行的这一个 Statement 有效;STATEMENT 级别粒度更细。

1.3 什么情况下会命中一级缓存

必须是在一个会话 Session当中,相同的 namespace(同一个命名空间 -> 同一个mapper文件) , sql 和 参数
不能够在查询之前执行 clearCache
中间不能执行 任何 update ,delete , insert (会将SqlSession中的数据全部清空)

mybatis清除一级缓存的几种方法

  1. 主动调用清理缓存的方法
sqlSession.clearCache()
  1. 提交事务,或者关闭session。
sqlSession.commit();
sqlSession.close();
  1. 执行增删改操作回清理缓存

1.4 内部结构

SqlSession 是一个接口,提供了一些 CRUD 的方法,而 SqlSession 的默认实现类是 DefaultSqlSession,DefaultSqlSession 类持有 Executor 接口对象,而 Executor 的默认实现是 BaseExecutor 对象,每个 BaseExecutor 对象都有一个 PerpetualCache 缓存,也就是上图的 Local Cache。
在这里插入图片描述

PerpetualCache

内部持有 HashMap,对一级缓存的操作实则是对 HashMap 的操作。

public class PerpetualCache implements Cache {private final String id;private Map<Object, Object> cache = new HashMap();...
}

1.5 clear() == map.clear()

在这里插入图片描述
也就是说一级缓存的底层数据结构就是 HashMap。所以说 cache.clear() 其实就是 map.clear(),也就是说,缓存其实是本地存放的一个 map 对象,每一个 SqlSession 都会存放一个 map 对象的引用。

public class PerpetualCache implements Cache {...private Map<Object, Object> cache = new HashMap();public void clear() {this.cache.clear();}...
}

insert/delete/update 方法, 清空 localCache

而为了保证缓存里面的数据肯定是准确数据避免脏读,每次我们进行数据修改后(增、删、改操作)就会执行commit操作,清空缓存区域。

1.6 Mybatis的一级缓存时序图

在这里插入图片描述

1.7 一级缓存实验

一级缓存同一个会话共享数据

@Test
public void firstLevelCacheFindUserById() {// 第一次查询id为1的用户User user1 = userMapper.findUserById(1);// 第二次查询id为1的用户User user2 = userMapper.findUserById(1);System.out.println(user1);System.out.println(user2);System.out.println(user1 == user2);
}

在这里插入图片描述
我们可以看到,只有第一次真正查询了数据库,后续的查询使用了一级缓存。

同一个会话如果有更新操作则缓存清除

增加了对数据库的修改操作,验证在一次数据库会话中,如果对数据库发生了修改操作,一级缓存是否会失效。

@Test
public void firstLevelCacheOfUpdate() {// 第一次查询id为1的用户User user1 = userMapper.findUserById(1);System.out.println(user1);// 更新用户User user = new User();user.setId(2);user.setUsername("tom");System.out.println("更新了" + userMapper.updateUser(user) + "个用户");// 第二次查询id为1的用户User user2 = userMapper.findUserById(1);System.out.println(user2);System.out.println(user1 == user2);
}

在这里插入图片描述
我们可以看到,在修改操作后执行的相同查询,查询了数据库,一级缓存失效。

一级缓存在多会话中会导致脏数据

开启两个 SqlSession,在 sqlSession1 中查询数据,使一级缓存生效,在 sqlSession2 中更新数据库,验证一级缓存只在数据库会话内部共享。

@Test
public void firstLevelCacheOfScope() {SqlSession sqlSession2 = sqlSessionFactory.openSession(true);UserMapper userMapper2 = sqlSession2.getMapper(UserMapper.class);System.out.println("userMapper读取数据: " + userMapper.findUserById(1));System.out.println("userMapper读取数据: " + userMapper.findUserById(1));// 更新用户User user = new User();user.setId(1);user.setUsername("andy");System.out.println("userMapper2更新了" + userMapper2.updateUser(user) + "个用户");System.out.println("userMapper读取数据: " + userMapper.findUserById(1));System.out.println("userMapper2读取数据: " + userMapper2.findUserById(1));
}

在这里插入图片描述
sqlSession2 更新了 id 为 1 的用户的姓名,从 riemann 改为了 andy,但 session1 之后的查询中,id 为 1 的学生的名字还是 riemann,出现了脏数据,也证明了之前的设想,一级缓存只在数据库会话内部共享。

解决方式:在配置一级缓存作用范围的时候将其设置为 STATEMENT,那么缓存仅对当前执行的语句有效,当语句执行完毕后,缓存就会被清空。

<settings><setting name="localCacheScope" value="STATEMENT"/>
</settings>

2. 二级缓存

2.2 二级缓存工作流程

在上文中提到的一级缓存中,其最大的共享范围就是一个 SqlSession 内部,如果多个 SqlSession 之间需要共享缓存,则需要使用到二级缓存。开启二级缓存后,会使用 CachingExecutor 装饰 Executor,进入一级缓存的查询流程前,先在 CachingExecutor 进行二级缓存的查询,具体的工作流程如下所示。
在这里插入图片描述
二级缓存开启后,同一个 namespace 下的所有操作语句,都影响着同一个 Cache,即二级缓存被多个 SqlSession 共享,是一个全局的变量。
当开启缓存后,数据的查询执行的流程就是 二级缓存 -> 一级缓存 -> 数据库。

MyBatis 是默认关闭二级缓存的,因为对于增删改操作频繁的话,那么二级缓存形同虚设,每次都会被清空缓存。

2.2 二级缓存配置

和一级缓存默认开启不一样,二级缓存需要我们手动开启。

  1. 全局配置文件 SqlMapConfig.xml
<!--开启二级缓存-->
<settings><setting name="cacheEnabled" value="true"/>
</settings>
  1. 在 UserMapper.xml 文件中开启二级缓存

mapper 代理模式

<!--开启二级缓存-->
<cache />

注解开发模式

@CacheNamespace(implementation = PerpetualCache.class) // 开启二级缓存
public interface UserMapper {
}

开启二级缓存后,还需要将要缓存的实体类去实现 Serializable 序列化接口,为了将缓存数据取出执行反序列化操作,因为二级缓存数据存储介质多种多样,不一定只存在内存中,有可能存在硬盘中,如果我们再取出这个缓存的话,就需要反序列化。所以 MyBatis 的所有 pojo 类都要去实现 Serializable 序列化接口。

二级缓存何时存入

在关闭sqlsession后(close),才会把该sqlsession一级缓存中的数据添加到namespace的二级缓存中。

二级缓存如何清空

当对SqlSession执行更新操作(update、delete、insert)后并执行commit时,不仅清空其自身的一级缓存(执行更新操作的效果),也清空二级缓存(执行commit()的效果)。

2.3 二级缓存实验

测试二级缓存与 SqlSession 无关

@Test
public void secondLevelCache() {SqlSession sqlSession1 = sqlSessionFactory.openSession();SqlSession sqlSession2 = sqlSessionFactory.openSession();UserMapper userMapper1 = sqlSession1.getMapper(UserMapper.class);UserMapper userMapper2 = sqlSession2.getMapper(UserMapper.class);// 第一次查询id为1的用户User user1 = userMapper1.findUserById(1);sqlSession1.close(); // 清空一级缓存System.out.println(user1);// 第二次查询id为1的用户User user2 = userMapper2.findUserById(1);System.out.println(user2);System.out.println(user1 == user2);
}

在这里插入图片描述
第一次查询时,将查询结果放入缓存中,第二次查询,即使 sqlSession1.close(); 清空了一级缓存,第二次查询依然不发出 sql 语句。
这里的你可能有个疑问,这里不是二级缓存了吗?怎么 user1 与 user2 不相等?

这是因为二级缓存的是数据,并不是对象。而 user1 与 user2 是两个对象,所以地址值当然也不想等。

测试执行 commit(),二级缓存数据清空

@Test
public void secondLevelCacheOfUpdate() {SqlSession sqlSession1 = sqlSessionFactory.openSession();SqlSession sqlSession2 = sqlSessionFactory.openSession();SqlSession sqlSession3 = sqlSessionFactory.openSession();UserMapper userMapper1 = sqlSession1.getMapper(UserMapper.class);UserMapper userMapper2 = sqlSession2.getMapper(UserMapper.class);UserMapper userMapper3 = sqlSession3.getMapper(UserMapper.class);// 第一次查询id为1的用户User user1 = userMapper1.findUserById(1);sqlSession1.close(); // 清空一级缓存User user = new User();user.setId(3);user.setUsername("edgar");userMapper3.updateUser(user);sqlSession3.commit(); //清空二级缓存// 第二次查询id为1的用户User user2 = userMapper2.findUserById(1);sqlSession2.close();System.out.println(user1 == user2);
}

在这里插入图片描述
在 sqlSession3 更新数据库,并提交事务后,sqlsession2 的 UserMapper namespace 下的查询走了数据库,没有走 Cache。

多表操作一定不能使用缓存

首先不管多表操作写到那个namespace下,都会存在某个表不在这个namespace下的情况。
例如两个表:role和user_role,如果我想查询出某个用户的全部角色role,就一定会涉及到多表的操作。

<select id="selectUserRoles" resultType="UserRoleVO">select * from user_role a,role b where a.roleid = b.roleid and a.userid = #{userid}
</select>

不管是写到RoleMapper.xml还是UserRoleMapper.xml,或者是一个独立的XxxMapper.xml中。如果使用了二级缓存,都会导致上面这个查询结果可能不正确。
如果你正好修改了这个用户的角色,上面这个查询使用缓存的时候结果就是错的。
这点应该很容易理解。

useCache 和 flushCache

<select id="findAll" resultMap="userMap" useCache="false" flushCache="true">select * from user u left join orders o on u.id = o.uid
</select>

设置 statement 配置中的 flushCache=“true” 属性,默认情况下为 true,即刷新缓存,一般执行完 commit 操作都需要刷新缓存,flushCache=“true” 表示刷新缓存,这样可以避免增删改操作而导致的脏读问题。默认不要配置。

<select id="findAll" resultMap="userMap" useCache="false">select * from user u left join orders o on u.id = o.uid
</select>

useCache 是用来设置是否禁用二级缓存的,在 statement 中设置 useCache=“false”,可以禁用当前 select 语句的二级缓存,即每次都会去数据库查询。

参考文章:
深入浅出 MyBatis 的一级、二级缓存机制
Mybatis 一级缓存
mybatis的一级缓存和二级缓存

相关文章:

MyBatis 的一级、二级缓存机制

目录标题缓存什么是缓存为什么使用缓存什么样的数据能使用缓存&#xff0c;什么样的数据不能使用适用于缓存不适用于缓存MyBatis 一级缓存、二级缓存关系1. 一级缓存1.1 什么是一级缓存mybatis1.2 一级缓存配置1.3 什么情况下会命中一级缓存mybatis清除一级缓存的几种方法1.4 内…...

剑指 Offer 65. 不用加减乘除做加法

摘要 剑指 Offer 65. 不用加减乘除做加法 一、位运算 有符号整数通常用补码来表示和存储&#xff0c;补码具有如下特征&#xff1a; 正整数的补码与原码相同&#xff1b;负整数的补码为其原码除符号位外的所有位取反后加 11。可以将减法运算转化为补码的加法运算来实现。符…...

5年软件测试年薪30w+,我的坎坷之路谁又知道

在深圳做了五年软件测试工作&#xff0c;从之前的一脸懵的点点点&#xff0c;到现在会自动化测试&#xff0c;说一点点非计算机专业人员从事软件测试的心得体会&#xff0c;仅供参考交流。 大部分测试在公司没啥地位&#xff0c;当然如果你懂技术就还行&#xff0c;单纯点点点…...

【Opencv--自适应图像二值化】cv2.adaptiveThreshold()

【Opencv–adaptiveThreshold】自适应阈值图像二值化 文章目录【Opencv--adaptiveThreshold】自适应阈值图像二值化1. 介绍2. adaptiveThreshold函数2.1 函数调用2.2 补充说明3. 代码示例4. 效果4.1 原图&#xff08;ori.img&#xff09;4.2 处理后5. 参考1. 介绍 在这里 cv2.…...

洛谷P8601[蓝桥杯][2013年第四届真题]剪格子

题目描述如图 11 所示&#xff0c;33 的格子中填写了一些整数。我们沿着图中的红色线剪开&#xff0c;得到两个部分&#xff0c;每个部分的数字和都是 60。本题的要求就是请你编程判定&#xff1a;对给定的 mn 的格子中的整数&#xff0c;是否可以分割为两个部分&#xff0c;使…...

配置alias实现快速生成.gitignore文件

git工具&#xff1a;版本控制开发工具。 cscope工具&#xff1a;用于浏览C源码的工具&#xff0c;类似于ctags。在代码根目录下执行cscope -Rbq&#xff0c;然后产生三个索引文件&#xff08;cscope.out、cscope.in.out和cscope.po.out三个文件&#xff09;。 在Linux下使用vi…...

MySQL数据库调优————GROUP BY及DISTINCT优化

GROUP BY 三种处理GROUP BY的方式 松散索引扫描&#xff08;Loose Index Scan&#xff09;紧凑索引扫描&#xff08;Tight Index Scan&#xff09;临时表&#xff08;Temporary table&#xff09; 三种方式的性能一次递减 松散索引扫描 无需扫描满足条件的所有索引键即可返…...

LRU缓存算法

双向链表哈希表&#xff08;非线程安全&#xff09; https://leetcode.cn/problems/lru-cache/solutions/259678/lruhuan-cun-ji-zhi-by-leetcode-solution/ /*** LRU算法: 哈希表双向链表实现* 1. 双向链表按照被使用的顺序来存储, 靠近头部的节点是最近使用的, 靠近尾部的节…...

@Configuration注解

Configuration注解介绍 Configuration注解&#xff0c;用于标注一个类是一个spring的配置类&#xff08;同时&#xff0c;也是一个bean&#xff09;&#xff0c;配置类中可以使用ComponentScan、Import、ImportResource 和 Bean等注解的方式定义beanDefinition。 Target(Elem…...

基于springboot+vue的食疗系统

基于springbootvue的食疗系统 ✌全网粉丝20W,csdn特邀作者、博客专家、CSDN新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取项目下载方式&#x1f345; 一、项目背景介绍&…...

sklearn学习-朴素贝叶斯

文章目录一、概述1、真正的概率分类器2、sklearn中的朴素贝叶斯二、不同分布下的贝叶斯1、高斯朴素贝叶斯GaussianNB2、探索贝叶斯&#xff1a;高斯朴素贝叶斯擅长的数据集3、探索贝叶斯&#xff1a;高斯朴素贝叶斯的拟合效果与运算速度总结一、概述 1、真正的概率分类器 算法…...

分享112个HTML艺术时尚模板,总有一款适合您

分享112个HTML艺术时尚模板&#xff0c;总有一款适合您 112个HTML艺术时尚模板下载链接&#xff1a;https://pan.baidu.com/s/1D3-mfPOud-f3vy9yLl-bmw?pwdfph2 提取码&#xff1a;fph2 Python采集代码下载链接&#xff1a;采集代码.zip - 蓝奏云 时尚平面模特网站模板 潮…...

用GDB远程调试运行于QEMU的程序

1. 前言 限于作者能力水平&#xff0c;本文可能存在谬误&#xff0c;因此而给读者带来的损失&#xff0c;作者不做任何承诺。 2. 测试环境 本文使用 Ubuntu 16.04.4 LTS QEMU 环境进行调试。 3. 用 GDB 调试 QEMU 内程序 3.1 编写用来调试的程序 我们用 ARM32 来进行调试…...

20 堆排序

文章目录1 堆排序的概念2 堆排序基本思想3 堆排序步骤图解说明4 堆排序的代码实现1 堆排序的概念 1) 堆排序是利用堆这种数据结构而设计的一种排序算法&#xff0c;堆排序是一种选择排序&#xff0c;它的最坏&#xff0c;最好&#xff0c;平均时间复杂度均为 O(nlogn)&#xf…...

2023最新文件快递柜系统网站源码 | 匿名口令分享 | 临时文件分享

内容目录一、详细介绍二、效果展示1.部分代码2.效果图展示三、学习资料下载一、详细介绍 2023最新文件快递柜系统网站源码 | 匿名口令分享 | 临时文件分享 很多时候&#xff0c;我们都想将一些文件或文本传送给别人&#xff0c;或者跨端传递一些信息&#xff0c;但是我们又不…...

分片策略(二)

分片策略 基本概念 分片键 用于分片的字段&#xff0c;是将数据库或表拆分的字段&#xff0c;比如&#xff0c;我可以使用user_id作为分片键将用户数据分到不同的表中&#xff0c;这里的user_id就是分片键&#xff0c;除了这种单字段分片&#xff0c;ShardingSphere还支持多…...

Qt之调色板类QPalette的使用

文章目录QPalette调色板类前言代码知识点讲解QPalette调色板类 前言 Qt提供的调色板类QPalette专门用于管理部件的外观显示&#xff0c;相当于部件或对话框的调色板&#xff0c;管理他们所有的颜色信息。每个部件都包含一个QPalette对象&#xff0c;在显示时&#xff0c;按照…...

Kotlin 32. Kotlin 多语言支持

Kotlin 多语言支持 对于 Kotlin 来说&#xff0c;当我们新建一个项目时&#xff0c;会默认在 values/ 文件夹下&#xff0c;生成一个 strings.xml 文件。比如说&#xff0c; <resources><string name"app_name">exampleNewProject</string> <…...

【Flutter入门到进阶】Dart进阶篇---DartVM单线程设计原理

1 虚拟机的指令执行设计 1.1 虚拟机的分类 基于栈的虚拟机&#xff0c;比如JVM虚拟机 基于寄存器的虚拟机&#xff0c;比如Dalvik虚拟机 1.2 虚拟机的概念 首先问一个基本的问题&#xff0c;作为一个虚拟机&#xff0c;它最基本的要实现哪些功能&#xff1f; 他应该能够模拟…...

Dem和NvM(NVRAM Manager)的交集

NVRAM&#xff08;NvM&#xff09;提供了在NVRAM中存储数据Block的机制。 NVRAM Block&#xff08;最大大小取决于配置&#xff09;被分配给Dem&#xff0c;并由Dem实现事件状态信息和相关数据的永久存储&#xff08;例如通电复位&#xff09;。 ECU 状态管理器&#xff08;Ec…...

AI神经网络CNN/RNN/DNN/SNN的区别对比

@版权声明: 本文由 ChatGpt 创作; BiliBili: https://www.bilibili.com/video/BV17D4y1P7pM/?share_source=copy_web&vd_source=6d217e0ff6387a749dc570aba51d36fd 引言 随着人工智能技术的发展,神经网络作为人工智能的核心技术之一,被广泛应用于图像识别、语音识别、…...

【JavaWeb】一文学会JPA

✅✅作者主页&#xff1a;&#x1f517;孙不坚1208的博客 &#x1f525;&#x1f525;精选专栏&#xff1a;&#x1f517;JavaWeb从入门到精通&#xff08;持续更新中&#xff09; &#x1f4cb;&#x1f4cb; 本文摘要&#xff1a;本篇文章主要介绍JPA的概念、注解实现ORM规范…...

【安卓逆向】APK修改与反编译回编译

【安卓逆向】反编译修改APK回编译使用工具流程步骤Apktool相关安装与使用常用命令备查APK签名命令备查实战练习反编译查看修改的地方使用Apktool反编译得到产物文件夹并进行修改回编APK实用场景在日常开发我们可能需要替换某些资源或者修改某些代码&#xff0c;但是我们没有源码…...

【计组笔记04】计算机组成原理之多模块存储器、Cache高速缓存存储器、Cache地址映射

这篇文章,主要介绍计算机组成原理之多模块存储器、Cache高速缓存存储器、Cache地址映射。 目录 一、双口RAM和多模块存储器 1.1、存取周期 1.2、双口RAM 1.3、多模块存储器...

英语基础-状语的应用

1. 非谓语动词作状语 1. 试着翻译下列句子 当他是一个小孩子的时候&#xff0c;他很喜欢玩电脑游戏。 When he was a child, he liked playing computer games. 如果他通过考试&#xff0c;他妈妈就会给他买一台新电脑。 If he passes the examination, his mother will b…...

发表论文需要注意的两点(建议收藏)

在学习人工智能的过程中&#xff0c;论文有着重要的作用&#xff0c;无论是深入学术科研&#xff0c;还是毕业找工作&#xff0c;都离不开发表论文这一步骤&#xff0c;所以今天就和大家分享一些关于论文发表的经验&#xff0c;希望对大家有所帮助。 为什么要早点发表论文&…...

ISTQB-TM-大纲

1. 测试过程 1.1 简介 在 ISTQB 软件测试基础级认证大纲中已描述了基本的测试过程包括以下活动&#xff1a; 计划和控制分析和设计实施和执行评估出口准则和报告测试结束活动 基础级大纲认同这些活动虽然有逻辑顺序&#xff0c;但过程中的某些活动可能重叠&#xff0c;或并行…...

Java SPI 机制详解

在面向对象的设计原则中&#xff0c;一般推荐模块之间基于接口编程&#xff0c;通常情况下调用方模块是不会感知到被调用方模块的内部具体实现。一旦代码里面涉及具体实现类&#xff0c;就违反了开闭原则。如果需要替换一种实现&#xff0c;就需要修改代码。 为了实现在模块装…...

腾讯前端经典react面试题(附答案)

React 性能优化在哪个生命周期&#xff1f;它优化的原理是什么&#xff1f; react的父级组件的render函数重新渲染会引起子组件的render方法的重新渲染。但是&#xff0c;有的时候子组件的接受父组件的数据没有变动。子组件render的执行会影响性能&#xff0c;这时就可以使用s…...

Go语言基础(十五):垃圾回收机制(三色标记)

文章目录一、标记清除&#xff08;三色标记&#xff09;大致原理1、标记细节2、root对象二、垃圾回收触发机制垃圾回收&#xff08;Garbage Collection&#xff09;&#xff0c;是一种自动管理内存的机制。传统编程语言&#xff08;如C/C&#xff09;需要开发者对无用内存资源进…...

营销型企业网站例子/如何做网站的教程

开始->程序->Adobe Flex 3 SDK Command Prompt 输入 asdoc -source-path d:\flexProject\你的项目\src -doc-classes 主类名 这样会生成所有类的帮助文档 有时只生成一个类&#xff0c;如果想生成所有 asdoc -source-path d:\flexProject\你的项目\src -doc-sources d:\f…...

网站开发工具选择/百度seo关键词优化市场

51单片机是可以输出PWM的&#xff0c;比较的麻烦。此时需要用到内部定时器来实现&#xff0c;可用两个定时器实现&#xff0c;也可以用一个定时器实现。用两个定时器的方法是用定时器T0来控制频率&#xff0c;定时器T1来控制占空比。大致的的编程思路是这样的&#xff1a;T0定时…...

mvc做网站用的多不多/网站品牌推广公司

fixture作用范围 fixture里面有个scope参数可以控制fixture的作用范围:session > module > class > function fixture(scope"function", paramsNone, autouseFalse, idsNone, nameNone):"""使用装饰器标记fixture的功能** 作者&#xff1a;上…...

企业网站 联系我们/淘宝关键词排名查询

Apple 算是最重视应用开发体验的公司了.从Xib到StoryBoard,从Auto Layout到Size Class,每一次的更新,都会给iOS应用的开发带来不小的便利.但是,对于绝对多数iOS攻城狮来说,我们依然还是很害怕写UITabelVIew的自适应布局.当然,害怕不是因为我们不会写,或者本身有什么特殊的技术点…...

普陀微信网站建设/网络运营培训

事务“要么全部成功&#xff0c;要么全部失败”ACIDACID嘛&#xff0c;原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Durability)&#xff01;我们以从A账户转账50元到B账户为例进行说明一下ACID&#xff0c;四大特性。原子性根据定义&#xff0c;原子性…...

做个网站多少钱/百度关键词统计

更好的阅读体验点击原文链接 大家好&#xff0c;计算机视觉life经过几个月打磨&#xff0c;推出了激光SLAM逐行源码解析课程《Cartographer从入门到精通: 原理深剖源码逐行详解》&#xff0c;已经购买过我们的课程学员及知识星球用户均有优惠券&#xff08;见文末&#xff09;…...