diff --git a/docs/.vuepress/config.ts b/docs/.vuepress/config.ts
index 3b8da08..6670289 100644
--- a/docs/.vuepress/config.ts
+++ b/docs/.vuepress/config.ts
@@ -37,8 +37,9 @@ export default {
{text: '业务功能设计',link:'/design/business/'},
],
},
- { text: '数据库',
+ { text: '数据库|ORM框架',
children: [
+ {text: 'Mybatis',link:'/database/mybatis/'},
{text: 'MySQL',link:'/database/mysql/'},
{text: 'NoSQL',link:'/database/nosql/'},
{text: 'PostgreSQL',link:'/database/postgresql/'},
@@ -54,6 +55,7 @@ export default {
{ text: '支付系统', link: '/pay/' },
{ text: '工具集',
children: [
+ {text: 'Mac软件',link:'/tools/mac/'},
{text: 'Maven',link:'/tools/maven/'},
{text: 'Docker',link:'/tools/Docker/'},
{text: 'Git',link:'/tools/git/'},
diff --git "a/docs/database/mybatis/MyBatis\345\212\250\346\200\201SQL.md" "b/docs/database/mybatis/MyBatis\345\212\250\346\200\201SQL.md"
new file mode 100644
index 0000000..5d15cd6
--- /dev/null
+++ "b/docs/database/mybatis/MyBatis\345\212\250\346\200\201SQL.md"
@@ -0,0 +1,41 @@
+# MyBatis动态SQL
+
+![640](./image/640.png)
+
+## foreach
+
+```xml
+
+```
+
+
+
+## include
+
+引用其他mapepr
+
+```xml
+ ID,MAJOR,BIRTHDAY,AGE,NAME,HOBBY
+
+```
+
+本mapper:
+
+```xml
+
+ select * from student
+
+
+```
+
+
+
+参考:
+
+https://mp.weixin.qq.com/s/de55g6VPEU3_p8GvocXy3w
+
diff --git "a/docs/database/mybatis/MyBatis\345\270\270\347\224\250\346\241\206\346\236\266.md" "b/docs/database/mybatis/MyBatis\345\270\270\347\224\250\346\241\206\346\236\266.md"
new file mode 100644
index 0000000..1dc9fcf
--- /dev/null
+++ "b/docs/database/mybatis/MyBatis\345\270\270\347\224\250\346\241\206\346\236\266.md"
@@ -0,0 +1,11 @@
+# MyBatis常用框架
+
+[MyBatis-Flex - MyBatis-Flex 官方网站](https://mybatis-flex.com/)
+
+[MyBatis-Plus (baomidou.com)](https://baomidou.com/)
+
+[mybatis-plus-ext: mybatis-plus框架的拓展包,在框架原有基础上做了进一步的轻度封装,增强内容:免手写Mapper、多数据源自动建表、数据自动填充、自动关联查询、冗余数据自动更新、动态查询条件等。 (gitee.com)](https://gitee.com/dromara/mybatis-plus-ext)
+
+[mybatis-mp: 基于mybatis封装的框架,满足绝大常用的CRUD,拥有复杂SQL的制作能力)](https://gitee.com/mybatis-mp/mybatis-mp)
+
+[AutoTable: 基于java实体上的注解完成数据库表自动维护的框架 (gitee.com)](https://gitee.com/tangzc/auto-table)
diff --git "a/docs/database/mybatis/MyBatis\346\211\271\351\207\217\346\217\222\345\205\245.md" "b/docs/database/mybatis/MyBatis\346\211\271\351\207\217\346\217\222\345\205\245.md"
new file mode 100644
index 0000000..4928429
--- /dev/null
+++ "b/docs/database/mybatis/MyBatis\346\211\271\351\207\217\346\217\222\345\205\245.md"
@@ -0,0 +1,57 @@
+# MyBatis 批量插入
+
+1. for 循环批量插入
+2. 手动批量提交
+3. 集合方式批量新增
+
+## for 循环批量插入
+
+```xml
+
+
+ INSERT INTO XXXXXX (XXXXXX, XXXXXX)
+ VALUES(#{XXXXXX}, #{XXXXXX})
+
+
+```
+
+```java
+ for(int i = 0 ;i < 10000; i++) {
+ Mapper.insert(XXXXXX);
+ }
+```
+
+耗时较高,不推荐
+
+## 手动批量提交
+
+```java
+@Resource
+private SqlSessionTemplate sqlSessionTemplate;
+// 关闭自动提交
+SqlSession sqlSession = sqlSessionTemplate.getSqlSessionFactory().openSession(ExecutorType.BATCH, false);
+
+for(int i = 0 ;i < 10000; i++) {
+ Mapper.insert(XXXXXX);
+ }
+
+sqlSession.commit();
+```
+
+耗时较高,不推荐。
+
+##集合方式批量新增
+
+```xml
+
+
+ INSERT INTO XXXXXX (XXXXXX, XXXXXX)
+ VALUES
+
+ (#{XXXXXX}, #{XXXXXX})
+
+
+
+```
+
+推荐使用。
\ No newline at end of file
diff --git "a/docs/database/mybatis/MyBatis\350\207\252\345\256\232\344\271\211\346\217\222\344\273\266Interceptor.md" "b/docs/database/mybatis/MyBatis\350\207\252\345\256\232\344\271\211\346\217\222\344\273\266Interceptor.md"
new file mode 100644
index 0000000..094551f
--- /dev/null
+++ "b/docs/database/mybatis/MyBatis\350\207\252\345\256\232\344\271\211\346\217\222\344\273\266Interceptor.md"
@@ -0,0 +1,22 @@
+# MyBatis自定义插件Interceptor
+
+拦截器是一种基于 AOP(面向切面编程)的技术,它可以在目标对象的方法执行前后插入自定义的逻辑。MyBatis 定义了四种类型的拦截器,分别是:
+
+- Executor:拦截执行器的方法,例如 update、query、commit、rollback 等。可以用来实现缓存、事务、分页等功能。
+- ParameterHandler:拦截参数处理器的方法,例如 setParameters 等。可以用来转换或加密参数等功能。
+- ResultSetHandler:拦截结果集处理器的方法,例如 handleResultSets、handleOutputParameters 等。可以用来转换或过滤结果集等功能。
+- StatementHandler:拦截语句处理器的方法,例如 prepare、parameterize、batch、update、query 等。可以用来修改 SQL 语句、添加参数、记录日志等功能。
+
+## 应用场景
+
+- SQL 语句执行监控:可以拦截执行的 SQL 方法,打印执行的 SQL 语句、参数等信息,并且还能够记录执行的总耗时,可供后期的 SQL 分析时使用。
+- SQL 分页查询:MyBatis 中使用的 RowBounds 使用的内存分页,在分页前会查询所有符合条件的数据,在数据量大的情况下性能较差。通过拦截器,可以在查询前修改 SQL 语句,提前加上需要的分页参数。
+- 公共字段的赋值:在数据库中通常会有 createTime , updateTime 等公共字段,这类字段可以通过拦截统一对参数进行的赋值,从而省去手工通过 set 方法赋值的繁琐过程。
+- 数据权限过滤:在很多系统中,不同的用户可能拥有不同的数据访问权限,例如在多租户的系统中,要做到租户间的数据隔离,每个租户只能访问到自己的数据,通过拦截器改写 SQL 语句及参数,能够实现对数据的自动过滤。
+- SQL 语句替换:对 SQL 中条件或者特殊字符进行逻辑替换。
+
+
+
+参考:
+
+https://mp.weixin.qq.com/s/ZBrTlHRx8Bseq7gLQeQ_Kw
\ No newline at end of file
diff --git "a/docs/database/mybatis/MyBatis\350\207\252\345\256\232\344\271\211\347\261\273\345\236\213\345\244\204\347\220\206\345\231\250TypeHandler.md" "b/docs/database/mybatis/MyBatis\350\207\252\345\256\232\344\271\211\347\261\273\345\236\213\345\244\204\347\220\206\345\231\250TypeHandler.md"
new file mode 100644
index 0000000..d12851d
--- /dev/null
+++ "b/docs/database/mybatis/MyBatis\350\207\252\345\256\232\344\271\211\347\261\273\345\236\213\345\244\204\347\220\206\345\231\250TypeHandler.md"
@@ -0,0 +1,84 @@
+# MyBatis自定义类型处理器TypeHandler
+
+![image-20240320092527345](./image/image-20240320092527345.png)
+
+```java
+public interface TypeHandler {
+
+ /**
+ * 设置 PreparedStatement 的指定参数。
+ *
+ * @param ps PreparedStatement 对象。
+ * @param index 参数在 PreparedStatement 中的位置。
+ * @param parameter 要设置的参数值。
+ * @param jdbcType JDBC 类型。这是一个可选参数,可以用来控制设置参数时的行为。
+ * @throws SQLException 如果在设置参数时发生 SQL 异常。
+ */
+ void setParameter(PreparedStatement ps, int index, T parameter, JdbcType jdbcType) throws SQLException;
+
+ /**
+ * 从 ResultSet 中获取数据并转换为 Java 类型。
+ *
+ * @param rs ResultSet 对象。
+ * @param columnName 要获取的数据的列名。
+ * @return 转换后的 Java 类型数据。
+ * @throws SQLException 如果在获取数据时发生 SQL 异常。
+ */
+ T getResult(ResultSet rs, String columnName) throws SQLException;
+
+ /**
+ * 从 ResultSet 中获取数据并转换为 Java 类型。
+ *
+ * @param rs ResultSet 对象。
+ * @param columnIndex 要获取的数据的列索引。
+ * @return 转换后的 Java 类型数据。
+ * @throws SQLException 如果在获取数据时发生 SQL 异常。
+ */
+ T getResult(ResultSet rs, int columnIndex) throws SQLException;
+
+ /**
+ * 从 CallableStatement 中获取数据并转换为 Java 类型。
+ *
+ * @param cs CallableStatement 对象。
+ * @param columnIndex 要获取的数据的列索引。
+ * @return 转换后的 Java 类型数据。
+ * @throws SQLException 如果在获取数据时发生 SQL 异常。
+ */
+ T getResult(CallableStatement cs, int columnIndex) throws SQLException;
+}
+
+```
+
+## 配置方式
+
+1. 在Mapper.xml中声明(应用**单个**指定字段)
+
+ ```xml
+
+
+
+ ```
+
+2. 在springboot的yml配置文件中设置类型处理器所在的**包名**,不是处理器路径(应用到**全局**)
+
+ ```yml
+ mybatis-plus:
+ type-handlers-package: com.xxx.handler
+ ```
+
+3. 实体类指定类型处理器。**必须在实体类上加`@TableName(autoResultMap = true)`,否则不生效**
+
+
+```java
+@Data
+@Accessors(chain = true)
+@TableName(autoResultMap = true)
+public class User {
+}
+```
+
+
+
+参考材料:
+
+https://juejin.cn/post/7320211683871801363?utm_source=gold_browser_extension
diff --git "a/docs/database/mybatis/MybatisIDEA\346\217\222\344\273\266.md" "b/docs/database/mybatis/MybatisIDEA\346\217\222\344\273\266.md"
new file mode 100644
index 0000000..3664831
--- /dev/null
+++ "b/docs/database/mybatis/MybatisIDEA\346\217\222\344\273\266.md"
@@ -0,0 +1,13 @@
+# Mybatis IDEA插件
+
+MybatisCodeHelperPro:好用付费。
+
+
+
+MybatisX:免费
+
+
+
+Mybatis Log:
+
+
diff --git a/docs/database/mybatis/README.md b/docs/database/mybatis/README.md
new file mode 100644
index 0000000..d73ac32
--- /dev/null
+++ b/docs/database/mybatis/README.md
@@ -0,0 +1,20 @@
+# Mybatis
+
+代码位置:
+
+[MyBatis常用框架](./MyBatis常用框架.md)
+
+[MybatisIDEA插件](./MybatisIDEA插件.md)
+
+[MyBatis自定义类型处理器TypeHandler](./MyBatis自定义类型处理器TypeHandler.md)
+
+[MyBatis自定义插件Interceptor](./MyBatis自定义插件Interceptor.md)
+
+MyBatis一级缓存、二级缓存
+
+[MyBatis动态SQL](./MyBatis动态SQL.md)
+
+[MyBatis批量插入](./MyBatis批量插入.md)
+
+MyBatis设计模式
+
diff --git a/docs/database/mybatis/image/640.png b/docs/database/mybatis/image/640.png
new file mode 100644
index 0000000..78c91f6
Binary files /dev/null and b/docs/database/mybatis/image/640.png differ
diff --git a/docs/database/mybatis/image/image-20240320091034331.png b/docs/database/mybatis/image/image-20240320091034331.png
new file mode 100644
index 0000000..0a7f81a
Binary files /dev/null and b/docs/database/mybatis/image/image-20240320091034331.png differ
diff --git a/docs/database/mybatis/image/image-20240320091134884.png b/docs/database/mybatis/image/image-20240320091134884.png
new file mode 100644
index 0000000..074c4e2
Binary files /dev/null and b/docs/database/mybatis/image/image-20240320091134884.png differ
diff --git a/docs/database/mybatis/image/image-20240320091301081.png b/docs/database/mybatis/image/image-20240320091301081.png
new file mode 100644
index 0000000..6266cc2
Binary files /dev/null and b/docs/database/mybatis/image/image-20240320091301081.png differ
diff --git a/docs/database/mybatis/image/image-20240320092527345.png b/docs/database/mybatis/image/image-20240320092527345.png
new file mode 100644
index 0000000..5a05905
Binary files /dev/null and b/docs/database/mybatis/image/image-20240320092527345.png differ
diff --git a/docs/design/distributed/README.md b/docs/design/distributed/README.md
index 4bc52f4..29be2f4 100644
--- a/docs/design/distributed/README.md
+++ b/docs/design/distributed/README.md
@@ -14,6 +14,8 @@
## 分布式锁
+[Redis官方文档](./Redis官方文档.md)
+
[分布式锁概述](./分布式锁.md)
[Redis分布式锁](./Redis分布式锁.md)
diff --git "a/docs/design/distributed/Redis\345\256\230\346\226\271\346\226\207\346\241\243.md" "b/docs/design/distributed/Redis\345\256\230\346\226\271\346\226\207\346\241\243.md"
new file mode 100644
index 0000000..137f55d
--- /dev/null
+++ "b/docs/design/distributed/Redis\345\256\230\346\226\271\346\226\207\346\241\243.md"
@@ -0,0 +1,76 @@
+# Redis官方文档
+
+[Distributed Locks with Redis | Redis](https://redis.io/docs/manual/patterns/distributed-locks/)
+
+## 分布式锁的设计原则
+
+1. **互斥**(安全性):在任何给定时刻,只有一个客户端可以持有锁。
+
+2. **无死锁**(有效性):超时机制,即使锁定资源的客户端崩溃或被分区,也总是可以获得锁;
+
+3. **容错性**(有效性):只要大多数 Redis 节点都启动,客户端就可以获取和释放锁。
+4. **同源性**:A加的锁,不能被B解锁
+5. **非阻塞**:获取不到锁,不能无限期等待;
+6. **高性能**:加锁解锁是高性能的
+
+## 锁定到单个实例
+
+**加锁**:
+
+```lua
+SET resource_name my_random_value NX PX 30000
+```
+
+1. resource_name:本次业务有关的id。
+2. my_random_value:一串随机值,必须保证全局唯一。
+3. NX:当且仅当key不存在时,返回执行成功,否则执行失败。
+4. PX:30秒后,key将被自动删除。
+
+执行命令后返回成功,表明服务成功的获得了锁。
+
+**重试 + 重试间隔**:
+
+```java
+while ((!result) && retryTimes-- > 0) {
+
+}
+```
+
+**解锁**:采用lua脚本
+
+在删除key之前,一定要判断服务A持有的value与Redis内存储的value是否一致。如果贸然使用服务A持有的key来删除锁,则会误将服务B的锁释放掉。
+
+```lua
+if redis.call("get", KEYS[1])==ARGV[1] then
+ return redis.call("del", KEYS[1])
+else
+ return 0
+end
+```
+
+## 基于RedLock实现分布式锁
+
+假设有两个服务A、B都希望获得锁,有一个包含了5个redis master的Redis Cluster,执行过程大致如下:
+
+1. 客户端获取当前时间戳,单位: 毫秒
+2. 服务A轮寻每个master节点,尝试创建锁。(这里锁的过期时间比较短,一般就几十毫秒) RedLock算法会尝试在大多数节点上分别创建锁,假如节点总数为n,那么大多数节点指的是n/2+1。
+3. 客户端计算成功建立完锁的时间,如果建锁时间小于超时时间,就可以判定锁创建成功。如果锁创建失败,则依次(遍历master节点)删除锁。
+4. 只要有其它服务创建过分布式锁,那么当前服务就必须轮寻尝试获取锁
+
+## Redisson
+
+1. redisson所有指令都通过lua脚本执行,保证了操作的原子性
+2. redisson设置了watchdog看门狗,“看门狗”的逻辑保证了没有死锁发生
+3. redisson支持Redlock的实现方式。
+
+执行流程:
+
+1. 线程去获取锁,获取成功: 执行lua脚本,保存数据到redis数据库。
+2. 线程去获取锁,获取失败: 订阅了解锁消息,然后再尝试获取锁,获取成功后,执行lua脚本,保存数据到redis数据库。
+
+
+
+>参考文章
+>
+>https://pdai.tech/md/arch/arch-z-lock.html
+
diff --git a/docs/tools/mac/README.md b/docs/tools/mac/README.md
new file mode 100644
index 0000000..55ca07b
--- /dev/null
+++ b/docs/tools/mac/README.md
@@ -0,0 +1,34 @@
+# Mac常用软件
+
+别人整理的软件:
+
+https://github.com/jaywcjlove/awesome-mac/blob/master/README-zh.md
+
+## 已经安装的软件
+
+RunCat
+
+文本:
+
+- WPS Office
+-
+
+浏览器
+
+- Microsoft Edge
+- Google Chrome
+- Safari浏览器
+- Firefox
+
+聊天:
+
+- 钉钉
+- 微信
+
+音乐/视频:
+
+- QQ音乐
+
+研发:
+
+- Visual Studio Code