MyBatis

Posted 一只可爱的小狐狸

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MyBatis相关的知识,希望对你有一定的参考价值。

MyBatis

MyBatis发展

1)MyBatis 是 Apache 的一个开源项目 iBatis, 2010 年 6 月这个项目由 Apache Software Foundation 迁移到了 Google Code,随着开发团队转投 Google Code 旗下, iBatis3.x 正式更名为 MyBatis ,代码于 2013 年 11 月迁移到 Github

2)iBatis 一词来源于“internet”和“abatis”的组合,是一个基于 Java 的持久层框架。 iBatis 提供的持久层框架包括 SQL Maps 和 Data Access Objects(DAO)

MyBatis 简介

1) MyBatis 是支持定制化 SQL、存储过程以及高级映射的优秀的持久层框架

2) MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集

3) MyBatis可以使用简单的XML或注解用于配置和原始映射,将接口和Java的POJO(Plain Old Java Objects,普通的 Java 对象)映射成数据库中的记录

为什么要使用 MyBatis – 现有持久化技术的对比

1) JDBC 1 SQL 夹在 Java 代码块里,耦合度高导致硬编码内伤 2 维护不易且实际开发需求中 sql 是有变化,频繁修改的情况多见

2) Hibernate 和 JPA 1 长难复杂 SQL,对于 Hibernate 而言处理也不容易 2 内部自动生产的 SQL,不容易做特殊优化 3 基于全映射的全自动框架,大量字段的 POJO 进行部分映射时比较困难。导致数据 库性能下降

3) MyBatis 1 对开发人员而言,核心 sql 还是需要自己优化 2 sql 和 java 编码分开,功能边界清晰,一个专注业务、一个专注数据

什么是MyBatis?

  • MyBatis 是一款优秀的持久层框架,
  • 它支持自定义 SQL、存储过程以及高级映射。
  • MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。
  • MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。
  • MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis 。2013年11月迁移到Github。

持久化

数据持久化

  • 持久化就是将程序的数据在持久状态和瞬时状态转化的过程
  • 内存:断电即失
    • 数据库(jdbc),io文件持久化
    • 生活:冷藏,罐头,

为什么需要持久化?

  • 有一些东西,不能让他丢掉
  • 内存太贵了

持久层

Dao层、Service层、Controller层

  • 完成持久化工作的代码块
  • 层界限十分明显

为什么学mybatis?

  • 帮助程序员将数据存入到数据库中
  • 便于方便
  • 传统的JDBC代码太过于复杂了,简化,框架,自动化
  • 不用学习Mybatis也可以,学习了之后更容易上手
  • 优点:
    • 简单易学
    • 灵活
    • 解除sql与程序代码的耦合
    • 提供映射标签,支持对象与数据库的orm字段关系映射
    • 提供对象关系映射标签,支持对象关系组建维护
    • 提供xml标签,支持编写动态sql。
      最重要的一点:使用的人多!

MyBatis 全局配置文件

MyBatis 全局配置文件

  1. The MyBatis configuration contains settings and properties that have a dramatic effect on how MyBatis behaves.

MyBatis 的配置文件包含了影响 MyBatis 行为甚深的设置(settings )和属性 (properties)信息。

  1. 文件结构如下:

configuration 配置

properties 属性

settings 设置

typeAliases 类型命名

typeHandlers 类型处理器

objectFactory 对象工厂

plugins 插件

environments 环境

environment 环境变量

transactionManager 事务管理器

dataSource 数据源

databaseIdProvider 数据库厂商标识

mappers 映射器

properties 属性

  1. 可外部配置且可动态替换的,既可以在典型的 Java 属性文件中配置,亦可 通过 properties 元素的子元素来配置

  2. 然而 properties 的作用并不单单是这样,你可以创建一个资源文件,名为 jdbc.properties 的文件,将四个连接字符串的数据在资源文件中通过键值 对 (key=value)的方式放置,不要任何符号,一条占一行

    driverClassName=com.mysql.cj.jdbc.Driver
    userName=root
    password=123456
    url=jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf8&serverTimezone=UTC

3)在 environment 元素的 dataSource 元素中为其动态设置

<environments default="oracle">
<environment id="mysql">
<transactionManager type="JDBC" />
<dataSource type="POOLED">
<property name="driver" value="$jdbc.driver" />
<property name="url" value="$jdbc.url" />
<property name="username" value="$jdbc.username" />
<property name="password" value="$jdbc.password" />
</dataSource>
</environment>
    </environments>

settings 设置

  1. 这是 MyBatis 中极为重要的调整设置,它们会改变 MyBatis 的运行时行为。

<settings>
<setting name="cacheEnabled" value="true"/>
<setting name="lazyLoadingEnabled" value="true"/>
<setting name="multipleResultSetsEnabled" value="true"/>
<setting name="useColumnLabel" value="true"/>
<setting name="useGeneratedKeys" value="false"/>
<setting name="autoMappingBehavior" value="PARTIAL"/>
<setting name="autoMappingUnknownColumnBehavior" value="WARNING"/>
<setting name="defaultExecutorType" value="SIMPLE"/>
<setting name="defaultStatementTimeout" value="25"/>
<setting name="defaultFetchSize" value="100"/>
<setting name="safeRowBoundsEnabled" value="false"/>
<setting name="mapUnderscoreToCamelCase" value="false"/>
<setting name="localCacheScope" value="SESSION"/>
<setting name="jdbcTypeForNull" value="OTHER"/>
<setting name="lazyLoadTriggerMethods" value="equals,clone,hashCode,toString"/>
</settings> 

typeAliases 别名处理

  1. 类型别名是为 Java 类型设置一个短的名字,可以方便我们引用某个类

    <typeAlias type="com.cutestFox.model.Student" alias="Student"/>
    </typeAliases>	
    
  2. 类很多的情况下,可以批量设置别名这个包下的每一个类创建一个默认的别名,就是简 单类名小写

environments 环境配置

  1. MyBatis 可以配置多种环境,比如开发、测试和生产环境需要有不同的配置

  2. 每种环境使用一个 environment 标签进行配置并指定唯一标识符

  3. 可以通过environments标签中的default 属性指定一个环境的标识符来快速的切换环境

  4. environment-指定具体环境 id:指定当前环境的唯一标识 transactionManager、和 dataSource 都必须有

dataSource

type: UNPOOLED | POOLED | JNDI | 自定义 UNPOOLED:不使用连接池, UnpooledDataSourceFactory POOLED:使用连接池, PooledDataSourceFactory

JNDI: 在 EJB 或应用服务器这类容器中查找指定的数据源

自定义:实现 DataSourceFactory 接口,定义数据源的获取方式。

databaseIdProvider 数据库厂商标识

  1. MyBatis 可以根据不同的数据库厂商执行不同的语句

  2. 配置了 databaseIdProvider 后,在 SQL 映射文件中的增删改查标签中使用 databaseId 来指定数据库标识的别名

    select * from tbl_employee where id = #id
  3. MyBatis 匹配规则如下:

1 如果没有配置 databaseIdProvider 标签,那么 databaseId=null

2 如果配置了 databaseIdProvider 标签,使用标签配置的 name 去匹配数据库信息, 匹配上设置 databaseId=配置指定的值,否则依旧为 null

3 如果 databaseId 不为 null,他只会找到配置 databaseId 的 sql 语句

4 MyBatis 会加载不带 databaseId 属性和带有匹配当前数据库 databaseId 属性的 所有语句。如果同时找到带有 databaseId 和不带 databaseId 的相同语句,则后者 会被舍弃

mappers 映射器

  1. 用来在 mybatis 初始化的时候,告诉 mybatis 需要引入哪些 Mapper 映射文件

  2. mapper 逐个注册 SQL 映射文件

resource : 引入类路径下的文件

url : 引入网络路径或者是磁盘路径下的文件

class : 引入 Mapper 接口. 有 SQL 映射文件 , 要求 Mapper 接口与 SQL 映射文件同名同位置. 没有 SQL 映射文件 , 使用注解在接口的方法上写 SQL 语句.

<mappers>
<mapper resource="EmployeeMapper.xml" />
<mapper class="com.atguigu.mybatis.dao.EmployeeMapper"/>
<package name="com.atguigu.mybatis.dao"/>
</mappers>
  1. 使用批量注册,这种方式要求 SQL 映射文件名必须和接口名相同并且在同一目录下

MyBatis 映射文件

Mybatis 映射文件简介

  1. MyBatis 的真正强大在于它的映射语句,也是它的魔力所在。由于它的异常强大,映射 器的 XML 文件就显得相对简单。如果拿它跟具有相同功能的 JDBC 代码进行对比, 你会立即发现省掉了将近 95% 的代码。MyBatis 就是针对 SQL 构建的,并且比普通 的方法做的更好。

  2. SQL 映射文件有很少的几个顶级元素(按照它们应该被定义的顺序): cache – 给定命名空间的缓存配置。 cache-ref – 其他命名空间缓存配置的引用。 resultMap – 是最复杂也是最强大的元素,用来描述如何从数据库结果集中来加 载对象。

sql – 可被其他语句引用的可重用语句块。

insert – 映射插入语句

update – 映射更新语句

delete – 映射删除语句

select – 映射查询语

Mybatis 使用 insert|update|delete|select 完成 CRUD

select

  1. Mapper 接口方法

    public Employee getEmployeeById(Integer id );

  2. Mapper 映射文件

    select * from tbl_employee where id = $_parameter

insert

  1. Mapper 接口方法

    public Integer insertEmployee(Employee employee);

  2. Mapper 映射文件

    insert into tbl_employee(last_name,email,gender) values(#lastName,#email,#gender)

update

  1. Mapper 接口方法

    public Boolean updateEmployee(Employee employee);

  2. Mapper 映射文件

    update tbl_employee set last_name = #lastName, email = #email, gender = #gender where id = #id

delete

  1. Mapper 接口方法

    public void deleteEmployeeById(Integer id );

  2. Mapper 映射文件

    delete from tbl_employee where id = #id

参数传递

参数传递的方式

  1. 单个参数 可以接受基本类型,对象类型。这种情况 MyBatis 可直接使用这个参数,不需要经过任 何处理。

  2. 多个参数 任意多个参数,都会被 MyBatis 重新包装成一个 Map 传入。Map 的 key 是 param1, param2,或者 0,1…,值就是参数的值

  3. 命名参数 为参数使用@Param 起一个名字,MyBatis 就会将这些参数封装进 map 中,key 就是我 们自己指定的名字

  4. POJO 当这些参数属于我们业务 POJO 时,我们直接传递 POJO

  5. Map 我们也可以封装多个参数为 map,直接传递

  6. Collection/Array 会被 MyBatis 封装成一个 map 传入, Collection 对应的 key 是 collection,Array 对应的 key 是 array. 如果确定是 List 集合,key 还可以是 list.

参数处理

  1. 参数位置支持的属性: javaType、jdbcType、mode、numericScale、resultMap、typeHandler、jdbcTypeName、 expression

  2. 实际上通常被设置的是:可能为空的列名指定 jdbcType ,例如:

    insert into orcl_employee(id,last_name,email,gender)
    values(employee_seq.nextval,#lastName, ,jdbcType=NULL ,#email,#ge
    nder)

参数的获取方式

  1. #key:获取参数的值,预编译到 SQL 中。安全。

  2. key:获取参数的值,拼接到 SQL 中。有 SQL 注入问题。ORDER BY name

select 查询的几种情况

  1. 查询单行数据返回单个对象

    public Employee getEmployeeById(Integer id );

  2. 查询多行数据返回对象的集合

    public List getAllEmps();

  3. 查询单行数据返回 Map 集合

    public Map getEmployeeByIdReturnMap(Integer id );

  4. 查询多行数据返回 Map 集合 @MapKey(“id”) // 指定使用对象的哪个属性来充当 map 的 key

    public Map getAllEmpsReturnMap();

resultType 自动映射

  1. autoMappingBehavior 默认是 PARTIAL,开启自动映射的功能。唯一的要求是列名和 javaBean 属性名一致

  2. 如果 autoMappingBehavior 设置为 null 则会取消自动映射

  3. 数据库字段命名规范,POJO 属性符合驼峰命名法,如 A_COLUMN aColumn,我们可 以开启自动驼峰命名规则映射功能,mapUnderscoreToCamelCase=true

resultMap 自定义映射

  1. 自定义 resultMap,实现高级结果集映射

  2. id :用于完成主键值的映射

  3. result :用于完成普通列的映射

  4. association :一个复杂的类型关联;许多结果将包成这种类型

  5. collection : 复杂类型的集合

MyBatis 动态 SQL

MyBatis 动态 SQL

  1. 动态 SQL 是 MyBatis 强大特性之一。极大的简化我们拼装 SQL 的操作

  2. 动态 SQL 元素和使用 JSTL 或其他类似基于 XML 的文本处理器相似

  3. MyBatis 采用功能强大的基于 OGNL 的表达式来简化操作 if choose (when, otherwise) trim (where, set) foreach

  4. OGNL( Object Graph Navigation Language )对象图导航语言,这是一种强大的 表达式语言,通过它可以非常方便的来操作对象属性。 类似于我们的 EL,SpEL 等

访问对象属性: person.name

调用方法: person.getName()

调用静态属性/方法: @java.lang.Math@PI @java.util.UUID@randomUUID()

调用构造方法: new com.atguigu.bean.Person(‘admin’).name

运算符: +,-*,/,%

逻辑运算符: in,not in,>,>=,<,<=,==,!=

if where

  1. If 用于完成简单的判断.

  2. Where 用于解决 SQL 语句中 where 关键字以及条件中第一个 and 或者 or 的问题

    select id , last_name ,email , gender from tbl_employee and id = #id and last_name = #lastName and email = #email and gender = #gender

trim

  1. Trim 可以在条件判断完的 SQL 语句前后 添加或者去掉指定的字符

prefix: 添加前缀

prefixOverrides: 去掉前缀

suffix: 添加后缀

suffixOverrides: 去掉后缀

<select id="getEmpsByConditionTrim" resultType="com.cutestfox.mybatis.beans.Employee">
    select id , last_name ,email , gender
from tbl_employee
<trim prefix="where" suffixOverrides="and">
<if test="id!=null">
id = #id and
</if>
<if test="lastName!=null &amp;&amp; lastName!=&quot;&quot;">
last_name = #lastName and
</if>
<if test="email!=null and email.trim()!=''">
email = #email and
</if>
<if test="&quot;m&quot;.equals(gender) or
&quot;f&quot;.equals(gender)">
gender = #gender
</if>
</trim>
</select>

set

  1. set 主要是用于解决修改操作中 SQL 语句中可能多出逗号的问题

    update tbl_employee last_name = #lastName, email = #email , gender = #gender where id =#id

choose(when、otherwise)

  1. choose 主要是用于分支判断,类似于 java 中的 switch case,只会满足所有分支中的一个

    select id ,last_name, email,gender from tbl_employee id = #id last_name = #lastName email = #email gender = 'm'

foreach

  1. foreach 主要用户循环迭代

collection: 要迭代的集合

item: 当前从集合中迭代出的元素

open: 开始字符

close:结束字符

separator: 元素与元素之间的分隔符

index: 迭代的是

List 集合:

index 表示的当前元素的下标 迭代的 Map 集合:

index 表示的当前元素的 key

<select id="getEmpsByConditionForeach" resultType="com.cutestfox.mybatis.beans.Employee">
select id , last_name, email ,gender from tbl_employee where id in
<foreach collection="ids" item="curr_id" open="(" close=")"
         separator="," >
#curr_id
</foreach>
</select>

sql

  1. sql 标签是用于抽取可重用的 sql 片段,将相同的,使用频繁的 SQL 片段抽取出来,单 独定义,方便多次引用. 2) 抽取 SQL:

    select id , last_name, email ,gender from tbl_employee
  2. 引用 SQL:

MyBatis 缓存机制

缓存机制

  1. MyBatis 包含一个非常强大的查询缓存特性,它可以非常方便地配置和定制。缓存可以 极大的提升查询效率

  2. MyBatis 系统中默认定义了两级缓存 一级缓存 二级缓存

  3. 默认情况下,只有一级缓存(SqlSession 级别的缓存,也称为本地缓存)开启。

  4. 二级缓存需要手动开启和配置,他是基于 namespace 级别的缓存。

  5. 为了提高扩展性。MyBatis 定义了缓存接口 Cache。我们可以通过实现 Cache 接口来自 定义二级缓存

一级缓存的使用

  1. 一级缓存(local cache), 即本地缓存, 作用域默认为 sqlSession。当 Session flush 或 close 后, 该 Session 中的所有 Cache 将被清空。

  2. 本地缓存不能被关闭, 但可以调用 clearCache() 来清空本地缓存, 或者改变缓存的作 用域.

  3. 在 mybatis3.1 之后, 可以配置本地缓存的作用域. 在 mybatis.xml 中配置

  4. 一级缓存的工作机制 同一次会话期间只要查询过的数据都会保存在当前 SqlSession 的一个 Map 中 key: hashCode+查询的 SqlId+编写的 sql 查询语句+参数

一级缓存失效的几种情况

  1. 不同的 SqlSession 对应不同的一级缓存

  2. 同一个 SqlSession 但是查询条件不同

  3. 同一个 SqlSession 两次查询期间执行了任何一次增删改操作

  4. 同一个 SqlSession 两次查询期间手动清空了缓存

二级缓存的使用

  1. 二级缓存(second level cache),全局作用域缓存

  2. 二级缓存默认不开启,需要手动配置

  3. MyBatis 提供二级缓存的接口以及实现,缓存实现要求 POJO 实现 Serializable 接口

  4. 二级缓存在 SqlSession 关闭或提交之后才会生效

  5. 二级缓存使用的步骤:

    1 全局配置文件中开启二级缓存

    2 需要使用二级缓存的映射文件处使用 cache 配置缓存

    3 注意:POJO 需要实现 Serializable 接口

  6. 二级缓存相关的属性

    1 eviction=“FIFO”:缓存回收策略: LRU – 最近最少使用的:移除最长时间不被使用的对象。 FIFO – 先进先出:按对象进入缓存的顺序来移除它们。 SOFT – 软引用:移除基于垃圾回收器状态和软引用规则的对象。 WEAK – 弱引用:更积极地移除基于垃圾收集器状态和弱引用规则的对象。 默认的是 LRU。

    2 flushInterval:刷新间隔,单位毫秒 默认情况是不设置,也就是没有刷新间隔,缓存仅仅调用语句时刷新

    3 size:引用数目,正整数 代表缓存最多可以存储多少个对象,太大容易导致内存溢出

    4 readOnly:只读,true/false true:只读缓存;会给所有调用者返回缓存对象的相同实例。因此这些对象不能被 修改。这提供了很重要的性能优势。 false:读写缓存;会返回缓存对象的拷贝(通过序列化)。这会慢一些,但是安全, 因此默认是 false

缓存的相关属性设置

  1. 全局 setting 的 cacheEnable: 配置二级缓存的开关,一级缓存一直是打开的。

  2. select 标签的 useCache 属性: 配置这个 select 是否使用二级缓存。一级缓存一直是使用的

  3. sql 标签的 flushCache 属性: 增删改默认 flushCache=true。sql 执行以后,会同时清空一级和二级缓存。 查询默认 flushCache=false。

  4. sqlSession.clearCache():只是用来清除一级缓存

MyBatis 逆向工程

逆向工程

  1. MyBatis Generator: 简称 MBG,是一个专门为 MyBatis 框架使用者定制的代码生成器, 可以快速的根据表生成对应的映射文件,接口,以及 bean 类。支持基本的增删改查, 以及 QBC 风格的条件查询。但是表连接、存储过程等这些复杂 sql 的定义需要我们手 工编写

逆向工程的配置

  1. 导入逆向工程的 jar 包 mybatis-generator-core-1.3.2.jar

  2. 编写 MBG 的配置文件

    <?xml version="1.0" encoding="UTF-8"?>
  3. 运行代码生成器生成代码

    @Test
    public void testMBG() throws Exception
    List warnings = new ArrayList();
    boolean overwrite = true;
    File configFile = new File(“mbg.xml”);
    ConfigurationParser cp = new ConfigurationParser(warnings);
    Configuration config = cp.parseConfiguration(configFile);
    DefaultShellCallback callback = new DefaultShellCallback(overwrite);
    MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config, callback, warnings);
    myBatisGenerator.generate(null);

以上是关于MyBatis的主要内容,如果未能解决你的问题,请参考以下文章

mybatis学习 -每天一记(驼峰命名匹配)

SpringBoot+Mybatis关于开启驼峰映射的设置

Mybatis处理列名—字段名映射— 驼峰式命名映射

mybatis支持属性使用驼峰的命名

MyBatis驼峰命名方法问题解决方法

mybatis 支持属性使用驼峰的命名 返回map为啥不支持