MyBatis
- 什么是MyBatis 中文官方文档
MyBatis 是一款优秀的持久层框架,他支持自定义SQL、存储过程以及高级映射。MyBatis免除几乎所有的JDBC代码以及设置参数和获取结果集的工作。MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。
MyBatis的安装
要使用 MyBatis, 只需将 mybatis-x.x.x.jar 文件置于类路径(classpath)中即可。
如果使用 Maven 来构建项目,则需将下面的依赖代码置于 pom.xml 文件中:
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.11</version>
</dependency>
配置xml文件
MyBatis的XML文件必须使用以下格式
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
</configuration>
配置的内容需要写在标签内,且必须按照 http://mybatis.org/dtd/mybatis-3-config.dtd 中的标签先后顺序配置
mybatis 配置文件的主要的两个职责
1. 配置数据源
2. 管理映射文件
3. 设置类型别名
属性 (properties)
可以用来通过resource="配置文件"来读取配置好的属性,设置好的属性可以在整个配置文件中用来替换需要动态配置的属性值
- 如果一个属性在不只一个地方进行了配置,那么,MyBatis 将按照下面的顺序来加载:
首先读取在 properties 元素体内指定的属性。 然后根据 properties 元素中的 resource 属性读取类路径下属性文件,或根据 url 属性指定的路径读取属性文件,并覆盖之前读取过的同名属性。 最后读取作为方法参数传递的属性,并覆盖之前读取过的同名属性。 因此,通过方法参数传递的属性具有最高优先级,resource/url 属性中指定的配置文件次之,最低优先级的则是 properties 元素中指定的属性。
设置 (settings)
这是 MyBatis 中极为重要的调整设置,它们会改变 MyBatis 的运行时行为 具体属性可以参考官方文档,这里就列出几个常用的
<!-- 解决 查询 返回 Map 字段 值为 null 不显示 字段的问题 -->
<setting name="callSettersOnNulls" value="true"/>
<!-- 解决驼峰命名和 数据库蛇形命名相互转换的配置 -->
<setting name="mapUnderscoreToCamelCase" value="true"/>
类型别名(typeAliases)
- 类型别名可为 Java 类型设置一个缩写名字。 它仅用于 XML 配置,意在降低冗余的全限定类名书写。
- 如果 通过 package 设置别名,那么 别名的 名字 默认是 类名 (不区分大小写,推荐使用小写!)
插件(plugins)
MyBatis 允许你在映射语句执行过程中的某一点进行拦截调用。默认情况下,MyBatis 允许使用插件来拦截的方法调用 例如分页插件的配置
<plugins>
<plugin interceptor="com.github.pagehelper.PageInterceptor">
<!--合理化配置 分页的参数 , 当页码小于等于0的时候,查询第一页, 当页码大于总页数的时候,查询最后一页 -->
<property name="reasonable" value="true"/>
</plugin>
</plugins>
环境配置(environments)
MyBatis 可以配置成适应多种环境,这种机制有助于将 SQL 映射应用于多种数据库之中, 现实情况下有多种理由需要这么做。例如,开发、测试和生产环境需要有不同的配置;或者想在具有相同 Schema 的多个生产数据库中使用相同的 SQL 映射。还有许多类似的使用场景。
- 不过要记住:尽管可以配置多个环境,但每个 SqlSessionFactory 实例只能选择一种环境。所以,如果你想连接两个数据库,就需要创建两个 SqlSessionFactory 实例,每个数据库对应一个。
- environments 元素定义了如何配置环境。
<environments default="development">
<environment id="development">
<transactionManager type="JDBC">
<property name="..." value="..."/>
</transactionManager>
<dataSource type="POOLED">
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
</dataSource>
</environment>
</environments>
注意一些关键点:
- 默认使用的环境 ID(比如:default=“development”)。
- 每个 environment 元素定义的环境 ID(比如:id=“development”)。
- 事务管理器的配置(比如:type=“JDBC”)。
- 数据源的配置(比如:type=“POOLED”)。
- 默认环境和环境 ID 顾名思义。 环境可以随意命名,但务必保证默认的环境 ID 要匹配其中一个环境 ID。
参数具体信息可以参考官网文档
映射器(mappers)
既然 MyBatis 的行为已经由上述元素配置完了,我们现在就要来定义 SQL 映射语句了。 但首先,我们需要告诉 MyBatis 到哪里去找到这些语句。 在自动查找资源方面,Java 并没有提供一个很好的解决方案,所以最好的办法是直接告诉 MyBatis 到哪里去找映射文件。 你可以使用相对于类路径的资源引用,或完全限定资源定位符(包括 file:/// 形式的 URL),或类名和包名等。
<!-- 使用相对于类路径的资源引用 -->
<mappers>
<mapper resource="org/mybatis/builder/AuthorMapper.xml"/>
<mapper resource="org/mybatis/builder/BlogMapper.xml"/>
<mapper resource="org/mybatis/builder/PostMapper.xml"/>
</mappers>
<!-- 使用完全限定资源定位符(URL) -->
<mappers>
<mapper url="file:///var/mappers/AuthorMapper.xml"/>
<mapper url="file:///var/mappers/BlogMapper.xml"/>
<mapper url="file:///var/mappers/PostMapper.xml"/>
</mappers>
<!-- 使用映射器接口实现类的完全限定类名 -->
<mappers>
<mapper class="org.mybatis.builder.AuthorMapper"/>
<mapper class="org.mybatis.builder.BlogMapper"/>
<mapper class="org.mybatis.builder.PostMapper"/>
</mappers>
<!-- 将包内的映射器接口实现全部注册为映射器 -->
<mappers>
<package name="org.mybatis.builder"/>
</mappers>
xml 映射器
MyBatis 的真正强大在于它的语句映射,这是它的魔力所在。由于它的异常强大,映射器的 XML 文件就显得相对简单。如果拿它跟具有相同功能的 JDBC 代码进行对比,你会立即发现省掉了将近 95% 的代码。MyBatis 致力于减少使用成本,让用户能更专注于 SQL 代码。
xml 文件模板
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="对应的DaoMapper接口">
</mapper>
SQL 映射文件只有很少的几个顶级元素(按照应被定义的顺序列出):
- cache – 该命名空间的缓存配置。
- cache-ref – 引用其它命名空间的缓存配置。
- resultMap – 描述如何从数据库结果集中加载对象,是最复杂也是最强大的元素。
- sql – 可被其它语句引用的可重用语句块。
- insert – 映射插入语句。
- update – 映射更新语句。
- delete – 映射删除语句。
- select – 映射查询语句。
select ※
通过 映射查询语句
-
select 必须设置返回结果类型
resultType 设置的是查询单条记录的类型
-
如果 参数的类型是字面量类型 (8种基本数据类型+包装类 + String)且 有且只有一个参数,那么 #{} 中的占位符,可以任意 如果 参数中使用了 @Param 注解,那么只能使用 注解中提供的值作为占位符
-
模糊查询 ,需要通过 concat 函数 拼接 % , 在 MySQL数据库中,如果查询的条件 使用了 函数,那么 会导致索引失效
在 mybatis 中, 可以 通过 bind 标签, 来绑定变量 , name 是设置的变量名, value 是 要设置的变量值
sql
SQL片段 是通过 sql 标签定义的, 通过 include 标签 引入 对应的 SQL片段
MyBatis 中 ${} 和 #{} 的区别 (高频面试题)
#{} 是一个占位符 ,主要应用于 SQL中 值 的占位, 在执行的时候,会被自定替换成 ? ,
在底层进行拼接的时候,会自动 在值的前后 添加引号,也可以对值进行转义, 可以用来防止SQL注入
${} 是一个占位符, 主要应用于 SQL中的 结构上(非值), 在执行的时候,不会被替换成 ?
会将值 原义 输出,作为SQL结构的一部分
${} 不能滥用,因为会产生SQL注入的风险, 能用 #{} 就绝对不要使用 ${} 进行占位
结果映射 (resultMap )
resultMap 元素是 MyBatis 中最重要最强大的元素。它可以让你从 90% 的 JDBC ResultSets 数据提取代码中解放出来,并在一些情形下允许你进行一些 JDBC 不支持的操作。实际上,在为一些比如连接的复杂语句编写映射代码的时候,一份 resultMap 能够代替实现同等功能的数千行代码。ResultMap 的设计思想是,对简单的语句做到零配置,对于复杂一点的语句,只需要描述语句之间的关系就行了。
ResultMap 是一个高级结果映射 ,允许用户 定义 查询的字段名 和 实体 属性的对应的关系
高级映射结果
MyBatis 创建时的一个思想是:数据库不可能永远是你所想或所需的那个样子。 我们希望每个数据库都具备良好的第三范式或 BCNF 范式,可惜它们并不都是那样。 如果能有一种数据库映射模式,完美适配所有的应用程序,那就太好了,但可惜也没有。 而 ResultMap 就是 MyBatis 对这个问题的答案。
- constructor - 用于在实例化类时,注入结果到构造方法中
- idArg - ID 参数;标记出作为 ID 的结果可以帮助提高整体性能
- arg - 将被注入到构造方法的一个普通结果
- result – 注入到字段或 JavaBean 属性的普通结果
- column : 用来设置 查询的字段名
- property : 是用来设置 type类型对应的属性名
- javaType : 用来设置 属性的类型
- jdbcType : 用来设置 数据库的类型
- id – 一个 ID 结果;标记出作为 ID 的结果可以帮助提高整体性能 id 和 result的用法相同,标记 该映射的是一个主键
- association 一个复杂类型的关联;许多结果将包装成这种类型 嵌套结果映射 关联可以是 resultMap 元素,或是对其它结果映射的引用
- collection 一个复杂类型的集合 嵌套结果映射 集合可以是 resultMap 元素,或是对其它结果映射的引用
- discriminator 使用结果值来决定使用哪个 resultMap
- case 基于某些值的结果映射 嵌套结果映射 case 也是一个结果映射,因此具有相同的结构和元素;或者引用其它的结果映射
关联的嵌套 Select 查询
维护 一方的 关联关系属性
通过标签来嵌套select语句进行关联查询
- column 数据库中的列名,或者是列的别名
- select 用于加载复杂类型属性的映射语句的 ID 通常是调用需要执行的查询方法
- javaType 返回值类型
- property 查询的结果对应实体类中的具体属性
维护 多方 关联关系属性
通过标签来嵌套select语句进行关联查询 与类似 多了一个ofType属性
- ofType 用来指定 集合中每一条记录的类型, ofType 必须设置
缓存
MyBatis 内置了一个强大的事务性查询缓存机制,它可以非常方便地配置和定制。 为了使它更加强大而且易于配置,我们对 MyBatis 3 中的缓存实现进行了许多改进。
默认情况下,只启用了本地的会话缓存,它仅仅对一个会话中的数据进行缓存。 要启用全局的二级缓存,只需要在你的 SQL 映射文件中添加一行:
启用二级缓存, 会对映射文件中所有的 select 添加缓存效果, insert, update, delete 会更新缓存 在 select 标签上 useCache(使用缓存) 默认是 true , flushCache(清除缓存)
默认是 false 在 insert , update, delete 标签上, useCache 默认是false, flushCache 默认是 true
useCache , flushCache 要想生效,必须 启用 二级缓存
动态SQL
动态 SQL 是 MyBatis 的强大特性之一。如果你使用过 JDBC 或其它类似的框架,你应该能理解根据不同条件拼接 SQL 语句有多痛苦,例如拼接时要确保不能忘记添加必要的空格,还要注意去掉列表最后一个列名的逗号。利用动态
SQL,可以彻底摆脱这种痛苦。
if
相当于Java的if语句
- test 条件
choose、when、otherwise
相当于Java的if 、else if 、else
foreach
for 循环
- collection : 定义要遍历的数据
如果传入的参数类型是 List, 那么 collection中的值 写成 list 如果传入的参数类型是 数组 , 那么 collection中的值 写成 array 如果使用了 @Param 注解指定了名字,那么就使用指定的名字
- item : 代表 遍历过程中 的 每一条数据 对应的变量, 变量名符合标识符命名规范即可
- separator : 用来定义循环中 每一条数据的 分割符号
- index : 用来标记该条记录的索引, 从 0 开始
- nullable : 是否允许为空,
- open : 整个 循环 以 … 开始
- close: 整个循环 以 … 结尾
MyBatis idea插件
推荐使用MyBatisCodeHelperPro 但是是收费的 也可以使用免费的 MyBatisx但是会缺少部分功能