diff --git a/repos/courses/mybatis/01.MyBatis基础/03.核心配置文件.md b/repos/courses/mybatis/01.MyBatis基础/03.核心配置文件.md
new file mode 100644
index 000000000..492d0b5af
--- /dev/null
+++ b/repos/courses/mybatis/01.MyBatis基础/03.核心配置文件.md
@@ -0,0 +1,484 @@
+---
+title: 核心配置文件
+author: 查尔斯
+date: 2020/12/26 14:48
+categories:
+ - MyBatis快速入门
+tags:
+ - MyBatis
+ - ORM框架
+---
+
+# 核心配置文件
+
+## 前言
+
+**C:** 在上一篇,笔者带大家对 MyBatis 的核心对象做了介绍。本篇,笔者将继续带你学习 MyBatis,掌握对核心配置文件的使用。
+
+MyBatis 的核心/全局配置文件 mybatis-config.xml ,顾名思义就是对 MyBatis 系统的核心设置文件。包含有 MyBatis 运行时行为配置、类型别名配置、环境配置等。
+
+下方是核心配置文件的标签模板,笔者将对其中常用的一些标签的常用使用方式进行介绍。
+
+configuration 根节点
+- **properties** 属性配置
+
+- settings 运行时行为配置
+- **typeAliases** 类型别名配置
+- typeHandlers 类型处理器
+
+- objectFactory 对象工厂
+- plugins 插件配置
+- **environments** 环境配置
+ - environment 单个环境配置
+ - transactionManager 事务管理器配置
+ - dataSource 数据源配置
+- databaseIdProvider 数据库厂商标识
+- **mappers** 映射器配置
+
+::: tip 笔者说
+这些标签在使用时一定要注意标签的顺序和允许使用次数。Eclipse 中可以通过在标签上按 F2 查看该标签下的内容模型,即标签的顺序和允许使用次数。你看下图中画圈处就是各个标签的顺序,后面的 ?号 代表指定标签最多允许使用一次。
+:::
+
+
+## properties元素
+
+如果你学过 Maven,那 properties 元素应该不难理解。在 MyBatis 的核心配置文件中,有很多配置是可能经常需要变动或复用的,如果直接将值硬编码在对应位置,将不利于统一维护管理和复用。
+
+properties 元素的作用就体现出来了,它的使用方式有两种。
+
+### 内部编写
+
+**第一种使用方式,是内部编写配置** ,示例如下:
+
+```xml
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+### 外部引入
+
+**第二种使用方式,是在外部配置文件编写配置,然后通过 properties 引入外部配置** ,示例如下:
+
+在 classpath 下 添加 一个 properties 配置文件,记录各种配置信息。(此处笔者记录的是数据源信息)
+
+```
+# MySQL
+mysql.driver=com.mysql.jdbc.Driver
+mysql.url=jdbc:mysql://localhost:3306/mybatis_demo_db
+mysql.username=root
+mysql.password=root
+```
+```xml
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+::: tip 笔者说
+大家猜一下,如果这两种方式在同时使用时遇到了相同配置,那么哪种方式的配置会生效呢?
+
+测试思路: 可以先故意改错内部配置方式的 mysql.password 值,如果测试运行正常,说明外部配置生效了,反之则内部配置生效了。 也可以再故意调错外部的值试试。
+:::
+
+```xml
+
+
+
+
+```
+
+## settings元素(下篇讲解)
+
+settings 元素是用来设置和改变 MyBatis 在运行时的一些行为的。
+
+| **设置项** | **描述** | **允许值** | **默认值** |
+| ------------------- | :----------------------------------------------------------: | :-------------------: | :--------: |
+| cacheEnabled | 对在此配置文件下的所有cache进行全局性开/关设置 | true \| false | true |
+| lazyLoadingEnabled | 全局性设置懒加载。如果设为false,则所有相关联的都会被初始化加载 | true \| false | true |
+| autoMappingBehavior | MyBatis对于resultMap自动映射匹配级别 | NONE\|PARTIAL \|FULL | PARTIAL |
+| **……(9个)** | **......** | **......** | **......** |
+
+## typeAlias元素
+
+在 SQL 映射文件中,我们在使用到某些类型时,需要编写好对应的全类名,大量的使用时,繁琐不说还容易错,如下 resultType 属性示例。
+
+```xml
+
+```
+
+而typeAlias 元素就可以解决此问题,通过它的配置,可以为指定类型配置好别名,这样在 SQL 映射文件中就可以不用写全限定类名,而是直接使用配置的类型别名了。它的使用方式也有两种。
+
+### 单个配置
+
+**第一种使用方式:挨个对不同类型进行别名配置。**
+
+```xml
+
+
+
+
+```
+
+### 包扫描
+
+**第二种使用方式:当要配置别名的类型都在指定的 package 下时,可以直接开启包扫描,批量实现别名自动配置。**
+
+```xml
+
+
+
+
+
+```
+
+### 使用效果
+
+下方是有了类型别名配置之后,SQL 映射文件内使用类型的效果。
+
+```xml
+
+
+```
+
+::: tip 笔者说
+在 MyBatis 中有一个类 TypeAliasRegistry ,它的作用就是进行类型别名注册和解析,Java 中常见的类型都已经被它注册好了别名。
+:::
+
+```java
+package org.apache.ibatis.type;
+// ...略...
+public class TypeAliasRegistry {
+ /** Map<类型别名, 对应类型的Class对象> */
+ private final Map> typeAliases = new HashMap<>();
+ /** 在创建对象时进行常用 Java 类型的别名注册 */
+ public TypeAliasRegistry() {
+ // String 类型注册的别名为 string
+ registerAlias("string", String.class);
+
+ registerAlias("byte", Byte.class);
+ registerAlias("long", Long.class);
+ registerAlias("short", Short.class);
+ registerAlias("int", Integer.class);
+ registerAlias("integer", Integer.class);
+ registerAlias("double", Double.class);
+ registerAlias("float", Float.class);
+ registerAlias("boolean", Boolean.class);
+
+ registerAlias("byte[]", Byte[].class);
+ registerAlias("long[]", Long[].class);
+ registerAlias("short[]", Short[].class);
+ registerAlias("int[]", Integer[].class);
+ registerAlias("integer[]", Integer[].class);
+ registerAlias("double[]", Double[].class);
+ registerAlias("float[]", Float[].class);
+ registerAlias("boolean[]", Boolean[].class);
+
+ registerAlias("_byte", byte.class);
+ registerAlias("_long", long.class);
+ registerAlias("_short", short.class);
+ registerAlias("_int", int.class);
+ registerAlias("_integer", int.class);
+ registerAlias("_double", double.class);
+ registerAlias("_float", float.class);
+ registerAlias("_boolean", boolean.class);
+
+ registerAlias("_byte[]", byte[].class);
+ registerAlias("_long[]", long[].class);
+ registerAlias("_short[]", short[].class);
+ registerAlias("_int[]", int[].class);
+ registerAlias("_integer[]", int[].class);
+ registerAlias("_double[]", double[].class);
+ registerAlias("_float[]", float[].class);
+ registerAlias("_boolean[]", boolean[].class);
+
+ registerAlias("date", Date.class);
+ registerAlias("decimal", BigDecimal.class);
+ registerAlias("bigdecimal", BigDecimal.class);
+ registerAlias("biginteger", BigInteger.class);
+ registerAlias("object", Object.class);
+
+ registerAlias("date[]", Date[].class);
+ registerAlias("decimal[]", BigDecimal[].class);
+ registerAlias("bigdecimal[]", BigDecimal[].class);
+ registerAlias("biginteger[]", BigInteger[].class);
+ registerAlias("object[]", Object[].class);
+
+ registerAlias("map", Map.class);
+ registerAlias("hashmap", HashMap.class);
+ registerAlias("list", List.class);
+ registerAlias("arraylist", ArrayList.class);
+ registerAlias("collection", Collection.class);
+ registerAlias("iterator", Iterator.class);
+
+ registerAlias("ResultSet", ResultSet.class);
+ }
+
+ /**
+ * 解析别名
+ * @param string 要解析的别名
+ * @return 该别名对应的类型的Class对象
+ */
+ public Class resolveAlias(String string) {
+ try {
+ if (string == null) {
+ return null;
+ }
+ // MyBatis 在【别名自动配置】和【解析映射文件中别名】时,对别名进行了小写转换。
+ // 所以在使用别名的时候才不区分大小写。
+ String key = string.toLowerCase(Locale.ENGLISH);
+ Class value;
+ if (typeAliases.containsKey(key)) {
+ value = (Class) typeAliases.get(key);
+ } else {
+ value = (Class) Resources.classForName(string);
+ }
+ return value;
+ } catch (ClassNotFoundException e) {
+ throw new TypeException("Could not resolve type alias '" + string + "'. Cause: " + e, e);
+ }
+ }
+ // ...略...
+}
+```
+
+## environments元素
+
+MyBatis 可以配置成适应多种环境,这种机制有助于将 SQL 映射应用于多种数据库之中,现实情况下有多种理由需要这么做。例如,开发、测试和生产环境需要有不同的配置;或者想在具有相同 Schema的多个生产数据库中使用相同的 SQL 映射。还有许多类似的使用场景。
+
+**不过要记住:尽管可以配置多个环境,但每个 SqlSessionFactory 实例只能选择一种环境。**
+
+所以,如果你想连接两个数据库,就需要创建两个 SqlSessionFactory 实例,每个数据库对应一个。而如果是三个数据库,就需要三个实例,依此类推,记起来很简单:
+
+- **每个数据库对应一个 SqlSessionFactory 实例** [1]
+
+```xml
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+## mappers元素
+
+mappers 元素的作用就是用来告诉 MyBatis 去哪找我们编写的 SQL 语句,它的使用方式有两大类。
+
+### 指定映射文件
+
+这类方式主要是告诉 MyBatis 我们所编写的 SQL 映射文件的地址,我们之前在 [《快速入门》](./01.快速入门) 中使用的就是属于这类方式。它有两种实现:
+
+```xml
+
+
+
+
+```
+
+```xml
+
+
+
+
+```
+
+### 指定Mapper接口[重要]
+
+这类方式还要涉及到 SqlSession 对象的另一个使用形式:**Mapper接口开发**
+
+我们之前使用 SqlSession 是让它来直接执行指定的 SQL 语句。这种方式需要指明 SQL 映射文件 namespace的名字以及 SQL 语句的 id。因为是硬编码在代码中,维护时有诸多不便,例如:容易写错不说,还不利于我们在持久层采用面向接口编程思想。
+
+```java
+// 执行 SQL 语句
+List userList = sqlSession.selectList("userMapper.selectList");
+```
+
+而 Mapper 接口开发就可以有效解决此问题,实现方式如下:
+
+**第一步:先创建一个 Mapper 接口。** 前期就养成一个开发习惯,保持 Mapper 接口和对应 SQL 映射文件同名同包(虽然目前不同名也没事,但是先听话,养成习惯)。
+
+```java
+public interface UserMapper {
+
+ /**
+ * 查询用户列表
+ * @return
+ */
+ List selectList();
+
+}
+```
+
+
+
+**第二步:将 SQL 映射文件的 namespace 值改为对应 Mapper 接口的全限定类名。**
+
+```xml
+
+
+
+
+```
+
+**第三步:将 SQL 映射文件中的 SQL 语句和 Mapper 接口中的方法进行绑定。**
+
+```xml
+
+
+
+
+
+
+```
+
+**最后,我们在核心配置文件中,再配置好 Mapper 接口的全限定类名即可。**
+
+```xml
+
+
+
+
+```
+
+**测试一下。**
+
+```java
+@Test
+void testSelectList() throws IOException {
+
+ // 获取SqlSession对象
+ try (SqlSession sqlSession = MyBatisUtils.openSession()){
+
+ // 获取 Mapper 接口,而不再直接执行 SQL 语句
+ // 和以前 DAO 模式就非常相像了,只不过是 DAO 实现类变为了 SQL 映射文件
+ UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
+ // 执行方法
+ List userList = userMapper.selectList();
+
+ // 遍历数据
+ userList.forEach(System.out::println);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+}
+```
+
+另外,在核心配置文件中,大量的配置 Mapper 接口全限定类名,还是有些麻烦,所以 MyBatis 在这也支持包扫描配置。
+
+```xml
+
+
+
+
+```
+
+::: warning 笔者说
+Mapper 接口开发是我们以后主要使用的方式,必须掌握!
+:::
+
+## 参考文献
+
+[1]MyBatis 官网. MyBatis 配置[EB/OL]. https://mybatis.org/mybatis-3/zh/configuration.html. 2020-12-26
+
+## 后记
+
+::: info 笔者说
+对于技术的学习,笔者一贯遵循的步骤是:先用最最简单的 demo 让它跑起来,然后学学它的最最常用 API 和 配置让自己能用起来,最后熟练使用的基础上,在空闲时尝试阅读它的源码让自己能够洞彻它的运行机制,部分问题出现的原因,同时借鉴这些技术实现来提升自己的代码高度。
+
+所以在笔者的文章中,前期基本都是小白文,仅仅穿插很少量的源码研究。当然等小白文更新多了,你们还依然喜欢,后期会不定时专门对部分技术的源码进行解析。
+:::
diff --git a/repos/public/img/2021/11/202111242251170.png b/repos/public/img/2021/11/202111242251170.png
new file mode 100644
index 000000000..b1cad2e18
Binary files /dev/null and b/repos/public/img/2021/11/202111242251170.png differ
diff --git a/repos/public/img/2021/11/202111242252221.png b/repos/public/img/2021/11/202111242252221.png
new file mode 100644
index 000000000..4512898b2
Binary files /dev/null and b/repos/public/img/2021/11/202111242252221.png differ