# mybatis学习
**Repository Path**: 2452860/mybatis-learning
## Basic Information
- **Project Name**: mybatis学习
- **Description**: mybatis相关学习资料
- **Primary Language**: Unknown
- **License**: Not specified
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 2
- **Forks**: 0
- **Created**: 2021-05-11
- **Last Updated**: 2022-08-29
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# mybatis
## 参考文档
https://mybatis.org/mybatis-3/zh/index.html
http://mybatis.org/spring/zh/boot.html
http://mybatis.org/spring-boot-starter/mybatis-spring-boot-autoconfigure/
## 前言
> 在学习mybatis之前我们先来回顾一下原生的JDBC都做了些什么,为什么在有JDBC的前提下为还是出现了很多ORM持久层框架。
**JDBC编程三部曲**
1. 加载数据库驱动
2. 获取数据库连接对象
3. 创建Statement\PreparedStatement对象
```java
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
public class DbUtil {
public static final String URL = "jdbc:mysql:///test";
public static final String USER = "root";
public static final String PASSWORD = "123456";
public static void main(String[] args) throws Exception {
//1.加载驱动程序
Class.forName("com.mysql.jdbc.Driver");
//2. 获得数据库连接
Connection conn = DriverManager.getConnection(URL, USER, PASSWORD);
//3.操作数据库,实现增删改查
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("SELECT * FROM USER");
//如果有数据,rs.next()返回true
while(rs.next()){
System.out.println(rs.getString("name")+" 年龄:"+rs.getInt("age"));
}
}
}
```
**原生JDBC开发存在的问题**

## mybatis简介
为了解决原生JDBC开发过程中导致的问题,逐渐出现了很多持久层框架,这些持久层框架本质都是对JDBC进行了封装,通过封装来规避了JDBC开发中遇到的问题。mybatis就是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射。mybatis免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。mybatis可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。
它将数据库连接的相关信息配置到文件当中,避免了JDBC硬编码的问题,它可以集成数据库连接池避免了频繁创建和释放数据库链接,消耗系统资源的问题,他将sql语句写入到配置文件中,解决了sq硬编码的问题,他通过复杂映射将查出来的数据直接注入到实体对象中,避免了自己组织返回参数的问题。
## mybatis入门
### 安装
> 要使用mybatis,只需要将mybatis的相关jar包引入工程即可,如果用maven构建项目,只需在POM文件下引入相应坐标即可。
```xml
org.mybatis
mybatis
x.x.x
```
### 构建
每个基于MyBatis的应用都是以一个 SqlSessionFactory的实例为核心的。SqlSessionFactory的实例可以通过 SqlSessionFactoryBuilder 获得。而SqlSessionFactoryBuilder则可以从XML配置文件或一个预先配置的 Configuration实例来构建出SqlSessionFactory实例。
> 构建 SqlSessionFactory实例可以采用通过XML配置文件和JAVA代码进行构建,推荐使用XML构建。
#### 从XML中构建
从 XML 文件中构建 SqlSessionFactory的实例非常简单,建议使用类路径下的资源文件进行配置。
但也可以使用任意的输入流(InputStream)实例,比如用文件路径字符串或 file:// URL 构造的输入
流。MyBatis 包含一个名叫 Resources的工具类,它包含一些实用方法,使得从类路径或其它位置加载
资源文件更加容易。
```java
String resource = "mybatis-config.xml";//配置文件所在路径,相对于classpath路径
InputStream inputStream = Resources.getResourceAsStream(resource);//加载配置文件
SqlSessionFactory sqlSessionFactory = new
SqlSessionFactoryBuilder().build(inputStream);//生产SqlSession工厂对象
```
XML 文件中配置了关于mybatis工程的核心配置文件,包括了数据源相关的配置,起别名,加载properties文件以及加载SQL对应的mapper配置文件等信息。
#### 使用JAVA代码构建
> 如果你更愿意直接从 Java 代码而不是 XML 文件中创建配置,或者想要创建你自己的配置建造器,
> MyBatis 也提供了完整的配置类,提供了所有与 XML 文件等价的配置项 。
```java
DataSource dataSource = BlogDataSourceFactory.getBlogDataSource();
TransactionFactory transactionFactory = new JdbcTransactionFactory();
Environment environment = new Environment("development", transactionFactory,
dataSource);
Configuration configuration = new Configuration(environment);
configuration.addMapper(BlogMapper.class);
SqlSessionFactory sqlSessionFactory = new
SqlSessionFactoryBuilder().build(configuration);
```
### XML配置文件
MyBatis 的配置文件包含了会深深影响 MyBatis 行为的设置和属性信息。配置文档的顶层结构如
下
> configuration(配置)
>
> > - properties(属性)
> >
> > - settings(设置)
> >
> > - typeAliases(类型别名)
> >
> > - typeHandlers(类型处理器)
> >
> > - objectFactory(对象工厂)
> >
> > - plugins(插件)
> >
> > - environments(环境配置)
> >
> > > - [ ] environment(环境变量)
> > > - [ ] transactionManager(事务管理器)
> > > - [ ] dataSource(数据源)
> >
> > - databaseIdProvider(数据库厂商标识)
> >
> > - mappers(映射器)
#### properties(属性)
这些属性可以在外部进行配置,并可以进行动态替换。你既可以在典型的 Java 属性文件中配置这些属性,也可以在 properties 元素的子元素中设置。例如:
```xml
```
设置好的属性可以在整个配置文件中用来替换需要动态配置的属性值。比如:
```xml
```
> 如果配置文件中 jdbc.properties 包含了标签下的元素内容,那么标签下的元素内容将会被覆盖,同时SqlSessionFactoryBuilder.build() 的时候也可以传入属性值,如SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, environment, props); 如果同一个属性在不同的地方做了配置,那么mybatis默认的优先级是
>
> - 首先读取在 properties 元素体内指定的属性
>
> - 然后根据 properties 元素中的 resource 属性读取类路径下属性文件,或根据 url 属性指定的路径读取属性文件,并覆盖之前读取过的同名属性。
>
> - 最后读取作为方法参数传递的属性,并覆盖之前读取过的同名属性。
>
> 因此,通过方法参数传递的属性具有最高优先级,resource/url 属性中指定的配置文件次之,最低优先级的则是 properties 元素中指定的属性。
#### settings (属性)
> seetings 属性是mybatis中极为重要的配置属性,它可以改变mybatis的运行行为
| 设置名 | 描述 | 有效值 | 默认值 |
| -------------------------------- | ------------------------------------------------------------ | ------------------------------------------------------------ | ----------------------------------------------------- |
| cacheEnabled | 全局性地开启或关闭所有映射器配置文件中已配置的任何缓存。 | true \| false | true |
| lazyLoadingEnabled | 延迟加载的全局开关。当开启时,所有关联对象都会延迟加载。特定关联关系中可通过设置 `fetchType` 属性来覆盖该项的开关状态。 | true \| false | false |
| aggressiveLazyLoading | 开启时,任一方法的调用都会加载该对象的所有延迟加载属性。否则,每个延迟加载属性会按需加载(参考 `lazyLoadTriggerMethods`)。 | true \| false | false (在 3.4.1 及之前的版本中默认为 true) |
| multipleResultSetsEnabled | 是否允许单个语句返回多结果集(需要数据库驱动支持)。 | true \| false | true |
| useColumnLabel | 使用列标签代替列名。实际表现依赖于数据库驱动,具体可参考数据库驱动的相关文档,或通过对比测试来观察。 | true \| false | true |
| useGeneratedKeys | 允许 JDBC 支持自动生成主键,需要数据库驱动支持。如果设置为 true,将强制使用自动生成主键。尽管一些数据库驱动不支持此特性,但仍可正常工作(如 Derby)。 | true \| false | false |
| autoMappingBehavior | 指定 MyBatis 应如何自动映射列到字段或属性。NONE 表示关闭自动映射;PARTIAL 只会自动映射没有定义嵌套结果映射的字段。 FULL 会自动映射任何复杂的结果集(无论是否嵌套)。 | NONE, PARTIAL, FULL | PARTIAL |
| autoMappingUnknownColumnBehavior | 指定发现自动映射目标未知列(或未知属性类型)的行为。 `NONE`: 不做任何反应 `WARNING`: 输出警告日志(`'org.apache.ibatis.session.AutoMappingUnknownColumnBehavior'` 的日志等级必须设置为 `WARN`)`FAILING`: 映射失败 (抛出 `SqlSessionException`) | NONE, WARNING, FAILING | NONE |
| defaultExecutorType | 配置默认的执行器。SIMPLE 就是普通的执行器;REUSE 执行器会重用预处理语句(PreparedStatement);BATCH 执行器不仅重用语句还会执行批量更新。 | SIMPLE REUSE BATCH | SIMPLE |
| defaultStatementTimeout | 设置超时时间,它决定数据库驱动等待数据库响应的秒数。 | 任意正整数 | 未设置 (null) |
| defaultFetchSize | 为驱动的结果集获取数量(fetchSize)设置一个建议值。此参数只可以在查询设置中被覆盖。 | 任意正整数 | 未设置 (null) |
| defaultResultSetType | 指定语句默认的滚动策略。(新增于 3.5.2) | FORWARD_ONLY \| SCROLL_SENSITIVE \| SCROLL_INSENSITIVE \| DEFAULT(等同于未设置) | 未设置 (null) |
| safeRowBoundsEnabled | 是否允许在嵌套语句中使用分页(RowBounds)。如果允许使用则设置为 false。 | true \| false | False |
| safeResultHandlerEnabled | 是否允许在嵌套语句中使用结果处理器(ResultHandler)。如果允许使用则设置为 false。 | true \| false | True |
| mapUnderscoreToCamelCase | 是否开启驼峰命名自动映射,即从经典数据库列名 A_COLUMN 映射到经典 Java 属性名 aColumn。 | true \| false | False |
| localCacheScope | MyBatis 利用本地缓存机制(Local Cache)防止循环引用和加速重复的嵌套查询。默认值为 SESSION,会缓存一个会话中执行的所有查询。若设置值为 STATEMENT,本地缓存将仅用于执行语句,对相同 SqlSession 的不同查询将不会进行缓存。 | SESSION \| STATEMENT | SESSION |
| jdbcTypeForNull | 当没有为参数指定特定的 JDBC 类型时,空值的默认 JDBC 类型。某些数据库驱动需要指定列的 JDBC 类型,多数情况直接用一般类型即可,比如 NULL、VARCHAR 或 OTHER。 | JdbcType 常量,常用值:NULL、VARCHAR 或 OTHER。 | OTHER |
| lazyLoadTriggerMethods | 指定对象的哪些方法触发一次延迟加载。 | 用逗号分隔的方法列表。 | equals,clone,hashCode,toString |
| defaultScriptingLanguage | 指定动态 SQL 生成使用的默认脚本语言。 | 一个类型别名或全限定类名。 | org.apache.ibatis.scripting.xmltags.XMLLanguageDriver |
| defaultEnumTypeHandler | 指定 Enum 使用的默认 `TypeHandler` 。(新增于 3.4.5) | 一个类型别名或全限定类名。 | org.apache.ibatis.type.EnumTypeHandler |
| callSettersOnNulls | 指定当结果集中值为 null 的时候是否调用映射对象的 setter(map 对象时为 put)方法,这在依赖于 Map.keySet() 或 null 值进行初始化时比较有用。注意基本类型(int、boolean 等)是不能设置成 null 的。 | true \| false | false |
| returnInstanceForEmptyRow | 当返回行的所有列都是空时,MyBatis默认返回 `null`。当开启这个设置时,MyBatis会返回一个空实例。请注意,它也适用于嵌套的结果集(如集合或关联)。(新增于 3.4.2) | true \| false | false |
| logPrefix | 指定 MyBatis 增加到日志名称的前缀。 | 任何字符串 | 未设置 |
| logImpl | 指定 MyBatis 所用日志的具体实现,未指定时将自动查找。 | SLF4J \| LOG4J \| LOG4J2 \| JDK_LOGGING \| COMMONS_LOGGING \| STDOUT_LOGGING \| NO_LOGGING | 未设置 |
| proxyFactory | 指定 Mybatis 创建可延迟加载对象所用到的代理工具。 | CGLIB \| JAVASSIST | JAVASSIST (MyBatis 3.3 以上) |
| vfsImpl | 指定 VFS 的实现 | 自定义 VFS 的实现的类全限定名,以逗号分隔。 | 未设置 |
| useActualParamName | 允许使用方法签名中的名称作为语句参数名称。为了使用该特性,你的项目必须采用 Java 8 编译,并且加上 `-parameters` 选项。(新增于 3.4.1) | true \| false | true |
| configurationFactory | 指定一个提供 `Configuration` 实例的类。这个被返回的 Configuration 实例用来加载被反序列化对象的延迟加载属性值。这个类必须包含一个签名为`static Configuration getConfiguration()` 的方法。(新增于 3.2.3) | 一个类型别名或完全限定类名。 | 未设置 |
| shrinkWhitespacesInSql | 从SQL中删除多余的空格字符。请注意,这也会影响SQL中的文字字符串。 (新增于 3.5.5) | true \| false | false |
| defaultSqlProviderType | Specifies an sql provider class that holds provider method (Since 3.5.6). This class apply to the `type`(or `value`) attribute on sql provider annotation(e.g. `@SelectProvider`), when these attribute was omitted. | A type alias or fully qualified class name | Not set |
#### typeAliases (属性)
> 类型别名可为 Java 类型设置一个缩写名字。 它仅用于 XML 配置,意在降低冗余的全限定类名书写。例如:
```xml
```
> 也可以指定一个包名,MyBatis 会在包名下面搜索需要的 Java Bean ,比如:
```xml
```
#### typeHandlers (属性)
>MyBatis 在设置预处理语句(PreparedStatement)中的参数或从结果集中取出一个值时,都会用类型处理器将获取到的值以合适的方式转换成 Java 类型
无论是 MyBatis 在预处理语句(PreparedStatement)中设置一个参数时,还是从结果集中取出一个值时,都会用类型处理器将获取的值以合适的方式转换成 Java 类型。
通过类型处理器(TypeHandler),可以实现javaBean以某种方式存入数据库中,亦或是从数据库取出的数据如何映射为javaBean。
通过继承BaseTypeHandler类,我们可以定制这个类型处理器,已实现枚举类或是一个javaBean的存取和写入。
**处理枚举类型**
若想映射枚举类型 `Enum`,则需要从 `EnumTypeHandler` 或者 `EnumOrdinalTypeHandler` 中选择一个来使用。EnumTypeHandler存入数据库的是枚举的name,EnumOrdinalTypeHandler存入数据库的是枚举的位置。但是这两个并不好用,一般我们需要自己实现枚举的类型处理器。
#### objectFactory (属性)
> 每次 MyBatis 创建结果对象的新实例时,它都会使用一个对象工厂(ObjectFactory)实例来完成实例化工作。默认的对象工厂需要做的仅仅是实例化目标类,要么通过默认无参构造方法,要么通过存在的参数映射来调用带有参数的构造方法。如果想覆盖对象工厂的默认行为,可以通过创建自己的对象工厂来实现。比如:
```java
// ExampleObjectFactory.java
public class ExampleObjectFactory extends DefaultObjectFactory {
public Object create(Class type) {
return super.create(type);
}
public Object create(Class type, List constructorArgTypes, List