最近在学习MyBatis框架,我在这里记录一下学习MyBatis过程中的心得体会。

图片描述

Mybatis是什么?使用它我们可以做什么?

MyBatis是一个开源的数据持久层框架,它内部封装了通过JDBC访问数据库的操作,支持普通的SQL查询、存储过程和高级映射,几乎消除了所有的JDBC代码和参数的手工设置以及结果集的检索。MyBatis作为持久层框架,其主要思想是将程序中大量SQL语句剥离出来,配置在配置文件中,实现SQL的灵活配置。这样做的好处是将SQL与程序代码分离,可以在不修改程序代码的情况下,直接在配置文件中修改SQL。Mybatis通过简单的XML或者注解进行配置和原始映射,将实体类和SQL语句之间建立映射关系,是一种半自动化的ORM实现。

MyBatis官网:http://mybatis.org

Github:https://github.com/mybatis

MyBatis环境搭建

这里我们使用的编译程序以Eclipse为例。

下载jar包==>部署jar包==>编写configuration核心配置文件==>创建pojo实体类==>创建DAO接口==>创建SQL映射文件==>编写测试类

需要的jar包:

图片描述

创建MyBatis核心配置文件configuration.xml

MyBatis核心配置文件主要用于配置数据库连接和MyBatis运行时所需的各种特性,包含了设置和影响MyBatis行为的属性

图片描述

MyBatis的核心接口和类
图片描述

1)每个MyBatis的应用程序都以一个SqlSessionFactory对象的实例为核心。

2)首先获取SqlSessionFactoryBuilder对象,可以根据XML配置文件或Configuration类的实例构建该对象。

3)然后获取SqlSessionFactory对象,该对象实例可以通过SqlSessionFactoryBuilder对象来获得。

4)使用SqlSessionFactory对象获取SqlSession实例。
SqlSessionFactoryBuilder
负责构建SqlSessionFactory,提供多个build()方法的重载,主要分为三个:

build(Reader reader,String environment,Properties properties)

build(InputStream inputStream,String environment,Properties properties)

build(Configuration config)

最大的特点是用过即丢,一旦创建了SqlSessionFactory对象之后,这个类就不再需要存在了,因此SqlSessionFactoryBuilder的最佳作用范围就是存在于方法体内,也就是局部变量。
SqlSessionFactory
相当于创建SqlSession实例的工厂,可以通过SqlSessionFactory提供的openSession()方法来获取SqlSession实例。

SqlSessionFactory对象一旦创建,就会在整个应用运行过程中始终存在,没有理由去销毁或再创建它,并且在应用运行中也不建议多次创建SqlSession。因此SqlSessionFactory的最佳作用与是Application,即随着应用的生命周期一同存在。这就是所谓的单例模式(指在应用运行期间有且仅有一个实例)。

这里把SqlSessionFactory的代码进行优化,最简单的实现方式就是放在静态代码块下:

图片描述

这里使用了ThreadLocal管理Mybatis中SqlSession对象,保证SqlSession在线程(准确的说是一次请求)中的唯一性。
SqlSession
SqlSession是用于执行持久化操作的对象,类似于JDBC中的Connection。它提供了面向数据库执行SQL命令所需的所有方法,可以通过SqlSession实例直接运行已映射的SQL语句。

图片描述

SqlSession对应着一次数据库回话。由于数据库会话不是永久的,因此SqlSession的生命周期也不应该是永久的。相反,在每次访问数据库时都需要创建它。

需要注意的是,每个线程都有自己的SqlSession实例,SqlSession实例不能被共享,也不是线程安全的。因此最佳的作用域范围是request作用域或者方法体作用域内。

SqlSession的两种使用方式

1)通过SqlSession实例来直接执行已映射的SQL语句。

2)基于mapper接口方式操作数据。(接口的方法必须与SQL映射文件中SQL语句的ID一一对应)
MyBatis核心配置文件
properties元素

properties元素描述的都是外部化,可替代的属性。有以下两种方式实现:

1)可通过外部指定的方式,即配置在典型的Java属性配置文件中,并使用这些属性对配置项实现动态配置。

2)直接配置为xml,并使用这些属性对配置项实现动态配置。

settings元素

settings元素的作用是设置一些非常重要的设置选项,用于设置和改变MyBatis运行中的行为。

settings元素支持的属性
设置项描述允许值默认值
cacheEnabled对在此配置文件下的所有cache进行全局性开/关设置truefalsetrue
lazyLoadingEnabled全局性设置懒加载。如果设置为false,则所有相关联的都会被初始化加载truefalsetrue
autoMappingBehaviorMyBatis对于resultMap自动映射的匹配级别NONEPARTIALFULLPARTIAL

typeAliases元素
typeAliases元素的作用是配置类型别名,通过与MyBatis的SQL映射文件相关联,减少输入多余的完整类名,以简化操作。
environments元素

MyBatis可以配置多套运行环境,我们可以灵活选择不同的配置,从而将SQL映射应用到不同的数据库环境上。不管增加几套运行环境,都必须要明确选择出当前的唯一一个运行环境。
mappers元素
mappers:映射器,用来定义SQL的映射语句。

<mappers>
    <mapper resource="url">
</mappers>

1)使用类资源路径获取资源

2)使用URL获取资源
SQL映射文件
下面是关于SQL映射文件的几个顶级元素:

mapper:映射文件的根元素节点,只有一个属性namespace(命名空间),作用:

  用于区分不同的mapper,全局唯一。

  绑定DAO接口,即面向接口编程。当namespace绑定某一接口之后,可以不用写该接口的实体类,MyBatis会通过接口的完整限定名查找到对应的mapper配置来执行SQL语句。因此namespace的命名必须要和接口同名。

cache:配置给定命名空间的缓存。(性能较低,不推荐使用)

cache-ref:从其他命名空间引用缓存配置。

resultMap:用来描述数据库结果集和对象的对应关系。

sql:可以重用的SQL块,也可以被其他语句引用。

insert:映射插入语句。

update:映射更新语句。

delete:映射删除语句。

select:映射查询语句。
namespace的命名必须跟某个DAO接口同名,通属于DAO层,所以映射文件与该DAO接口应放置在同一package下。在不同的mapper文件中,子元素的id可以相同,MyBatis通过namespace和子元素的id联合区分。接口中的方法与映射文件中的SQL语句id应一一对应。resultType
resultType直接表示返回类型,包括基础数据类型和复杂数据类型。
resultMap
id属性:唯一标识,此id值用于select元素的resultMap属性的引用。

type属性:表示该resultMap的映射结果类型。

result子节点:用于标识一些简单属性,其中column属性表示从数据库中查询的字段名,property则表示查询出来的字段对应的值赋给实体对象的哪个属性。

resultMap是对外部resultMap定义的引用,对应外部resultMap的id,表示返回结果映射到某一个resultMap上。主要应用:数据库字段信息与对象属性不一致或者需要做复杂的联合查询以便自由控制映射结果。
resultType和resultMap本质上是一样的,都是Map数据结构。但是不能同时存在,只是二者选其一使用。association
association:映射到JavaBean的某个复杂类型属性,即JavaBean内部嵌套一个复杂数据类型属性。association仅处理一对一的关联关系。

属性:

javaType:完整Java类名或者别名。

property:映射数据库列的实体对象的属性。

id

result:

  property:映射数据库列的实体对象的属性。

  column:数据库列名或别名。
collection
collection元素的作用和association元素的作用类似,只不过collection元素映射的属性是一个集合列表,即JavaBean内部嵌套一个复杂数据类型(集合)属性。

属性:

ofType:完整Java类型或者别名,即集合所包含的类型。

property:映射数据库列的实体对象的属性。

collection的子元素与association基本一致。
resultMap自动映射级别
在MyBatis核心配置文件中添加标签:

<settings>
    <setting name="autoMappingBehavior" value="FULL" />
</settings>

MyBatis对resultMap自动映射有三个匹配级别:

NONE:禁止自动匹配。

PARTIAL(默认):自动匹配所有属性,有内部嵌套(association、collection)的除外。

FULL:自动匹配所有。
使用动态SQL完成多条件查询
if:利用if实现简单的条件选择。

choose(when,otherwise):相当于Java中的switch,通常与when和otherwise搭配。

where:简化SQL语句中where的条件判断,并能智能地处理and和or,不必担心多余关键字导致的语法错误。

set:解决动态更新语句。主要功能和where类似,是在包含的语句前输出一个set,若包含的语句是以逗号结束的,会自动把该逗号忽略掉,再配合if元素就可以动态地更新需要修改的字段。

trim:可以灵活地去除多余的关键字。

属性:

prefix:前缀,作用是通过自动识别是否有返回值后,在trim包含的内容上加上前缀。

suffix:后缀,作用是在trim包含的内容上加上后缀。

prefixOverrides:对于trim包含的首部进行指定内容的忽略。

suffixOverrides:对于trim包含内容的首尾部进行指定内容的忽略。

foreach:迭代一个集合,通常用于in条件。foreach主要用在构建in条件中,它可以在SQL语句中迭代一个集合。

属性:

item:表示集合中每一个元素进行迭代时的别名。

index:指定一个名称,用于表示在迭代过程中,每次迭代到的位置。

open:表示该语句以什么开始。(如果是in条件语句,以“(”开始)

separator:表示在每次进行迭代之间以什么符号作为分隔符。(如果是in条件语句,以“,”作为分隔符)

close:表示该语句以什么结束。(如果是in条件语句,以“)”结束)

collection:该属性必须指定,不同情况下,该属性的值是不一样的。主要有三种情况:

  若入参为单参数且参数类型是一个List的时候,collection属性值为list。

  若入参为单参数且参数类型是一个数组的时候,collection属性值为array。

  若传入参数为多参数,就需要把它们封装为一个Map进行处理。


MyBatis框架的优点:1)与JDBC相比,减少了50%以上的代码量。2)MyBatis是最简单的持久化框架,小巧并且简单易学。3)MyBatis相当灵活,不会对应用程序或者数据库的现有设计强加任何影响,SQL写在XML里,从程序代码中彻底分离,降低耦合度,便于统一管理和优化,并可重用。4)提供XML标签,支持编写动态SQL语句。5)提供映射标签,支持对象与数据库的ORM字段关系映射。MyBatis框架的缺点:1)SQL语句的编写工作量较大,对开发人员编写SQL语句的功底有一定要求。2)SQL语句依赖于数据库,导致数据库移植性差,不能随意更换数据库。

补充:MyBatis 中 #{} 和 ${} 的区别

#{}: 解析为一个 JDBC 预编译语句(prepared statement)的参数标记符,一个 #{ } 被解析为一个参数占位符 。
${}: 仅仅为一个纯碎的 string 替换,在动态 SQL 解析阶段将会进行变量替换。以${}格式传入入参后的执行sql打乱了我们的预期sql格式及查询条件,从而实现sql注入。

使用${}的场景:
1 作为in条件时,
2 参数为int类型并且数据库中字段的类型是number,
3 表名
4 order by ${},排序字段

其余情况一般不使用 ${}。简单来说,就是能用 #{} 就不要用 ${}。