MyBatis框架入门


学习目录:

一、MyBatis是什么

二、第一个MyBatis程序

三、MyBatis三个基本要素

四、MyBatis执行SQL的两种方式

五、MyBatis标签

六、resultMap元素

七、关联(级联)查询

八、动态SQL

九、分页功能

十、缓存(一级缓存和二级缓存)

十一、逆向工程


一、MyBatis是什么

面试官让你一句话概括MyBatis是什么

MyBatis是一个开源的、轻量级的数据持久化框架。其内部封装了JDBC,简化了加载驱动、创建连接、创建statement等繁杂的中间过程,开发者只需要关注SQL语句本身。

面试官问你为什么要使用MyBatis框架,使用它有什么优点

1.首当其冲的就是它的免费开源。

2.简化了操作数据库的中间过程,与JDBC相比减少了50%以上的代码量。

3.SQL写在XML文件中,和程序的逻辑代码分离,降低了耦合度,方便SQL同一管理与优化。

4.提供了一些非常方便的SQL标签,支持编写动态SQL。

面试官问,那MyBatis有没有什么缺点呢?

1.不像Hibernate全自动的持久化框架,使用MyBtis框架需要编写大量的SQL语句,而且对开发人员编写SQL语句的功底有一定的要求。

2.编写的SQL语句过于依赖数据库,不同的数据库SQL语句是不一样的,所以项目不能轻易更换数据库,可移植性较差。


二、第一个MyBatis程序

面试官问,编写一个完整的MyBatis程序一共分为哪几步呢?

1.在数据库中建立数据库表。

2.在程序代码中创建数据库表对应的实体类DO。

3.创建xml映射文件,指定xml的namespace,使得数据库表与实体类之间形成对应关系。

4.创建MyBatis的核心配置文件mybatis-config.xml,配置数据源等信息,同时将mapper.xml文件加入到配置文件中。

5.测试,读取mybatis-config.xml配置文件,建造sql工厂,使用这个工厂生成数据库连接对象openSession,调用mapper方法进行测试。


三、MyBatis三个基本要素

1.MyBatis核心接口和类

2.MyBatis核心配置文件 mybatis-config.xml

3.MyBatis Mapper映射器

MyBatis核心接口和类有哪些?

SqlSessionFactoryBuilder

SqlSessionFactory

SqlSession

仔细讲讲

1.首先根据xml配置文件或者Configuration类的实例构建SqlSessionFactoryBuilder对象。

SqlSessionFactoryBuilder 的最大特点就是用过即丢。创建 SqlSessionFactory 对象之后,这个类就不存在了,因此 SqlSessionFactoryBuilder 的最佳范围就是存在于方法体内,也就是局部变量。

2.通过 SqlSessionFactoryBuilder 对象来构建SqlSessionFactory对象。

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

3.通过SqlSessionFactory 工厂对象,就可以获取 SqlSession 实例。SqlSession 对象中完全包含以数据库为背景的所有执行 SQL 操作的方法,用该实例可以直接执行已映射的 SQL 语句。

SqlSession 对应一次数据库会话。由于数据库会话不是永久的,因此 SqlSession 的生命周期也不是永久的,每次访问数据库时都需要创建 SqlSession 对象。
需要注意的是:每个线程都有自己的 SqlSession 实例,SqlSession 实例不能被共享,也不是线程安全的。因此 SqlSession 的作用域范围是 request 作用域或方法体作用域内。

面试官:给我们讲讲MyBatis核心配置文件 mybatis-config.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>
    <properties />
    <settings />
    <typeAliases />
    <typeHandlers />
    <objectFactory />
    <plugins />
    <environments>
        <environment>
            <transactionManager />
            <dataSource />
        environment>
    environments>
    <databaseIdProvider />
    <mappers />
configuration>

注意:上面结构的节点位置需要按照顺序设置,否则会报错。

其中常用的标签有哪些?

1.properties标签

用来加载指定的数据库连接信息

<properties resource="resources/db.properties"/>

2.settting标签里面有很多东西,但是一般不需要去主动设置,使用它的默认设置就好。

全量配置样例:

<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>

3.typeAliases标签

别名设置标签,设置了类的别名,在使用的时候就直接使用别名就好了,不需要每次都写全限定类名了。

<typeAliases>
    <typeAlias alias = "student" type = "xxx.xx.xx.Student"/>
typeAliases>

当然当类的数量太多了时,并不需要一个一个去设置,直接扫描整个包进行别名设置就好,别名就是类名的第一个字母小写。

<typeAliases>
    <package name="xxx.xxx.po"/>
typeAliases>

4.environments标签

配置 MyBatis 的多套运行环境

5.transactionManager标签

MyBatis 支持两个事务管理器,即 JDBC 和 MANAGED。
如果使用 JDBC 类型的事务管理器,则应用程序服务器负责事务管理操作,例如提交、回滚等。如果使用 MANAGED 类型的事务管理器,则应用程序服务器负责管理连接生命周期。

6.dataSource标签

配置连接数据库的信息

type 属性用于指定数据源类型

1)UNPOOLED

UNPOOLED 没有数据库连接池,效率低下。MyBatis 需要打开和关闭每个数据库操作的连接,它有点慢,通常应用于简单的应用程序。

2)POOLED

对于 POOLED 数据源类型,MyBatis 将维护一个数据库连接池。并且对于每个数据库的操作,MyBatis 都会使用连接池中的连接,并在操作完成后将它们返回到池中。减少了创建新连接所需的初始连接和身份验证时间。

3)JNDI

对于 JNDI 的数据源类型,MyBatis 将从 JNDI 数据源中获取连接。

<dataSource type="POOLED">
    
    <property name="driver" value="com.mysql.jdbc.Driver" />
    
    <property name="url"
        value="jdbc:mysql://localhost:3306/test?characterEncoding=utf8" />
    <property name="username" value="root" />
    <property name="password" value="root" />
dataSource>

7.mapper标签

用于指定 MyBatis SQL 映射文件的路径

<mappers>
    <mapper resource="xxx/xxx/mapper/Student.xml"/>
mappers>

同样,这里也可以用扫描整个包的方式,全部加入进来。

面试官:介绍一下MyBatis Mapper映射器

映射器是 MyBatis 中最重要的文件,文件中包含一组 SQL 语句(例如查询、添加、删除、修改),这些语句称为映射语句或映射 SQL 语句。

映射器由 Java 接口(mapper)和 XML 文件(或注解)共同组成。一一对应共同组成MyBatis映射器。

映射器的两种实现方式:

1.通过 XML 文件方式实现,比如我们在 mybatis-config.xml 文件中描述的 XML 文件,用来生成 mapper。

2.通过注解的方式实现,使用 Configuration 对象注册 Mapper 接口。即直接在Mapper接口里面的方法上直接使用注解形成映射器。


四、MyBatis执行SQL的两种方式

1.直接一步到位,通过 SqlSession 发送 指定的SQL语句。

示例:

Student student = (Student)sqlSession.selectOne("xxx.xxx.mapper.xxxMapper.getStudent",1);

通过操作数据库的对象sqlSession,明确指定需要指定的SQL语句和传递的参数。

2.分两步,中间借助mapper接口过度,通过 SqlSession 获取 Mapper 接口,通过 Mapper 接口发送 SQL。

示例:

StudentMapper studentMapper = sqlSession.getMapper(StudentMapper.class);
Student student = studentMapper.getStudent(1);

建议使用第二种

使用 Mapper 接口编程可以消除 SqlSession 带来的功能性代码,提高可读性。同时,使用第二种方式IDE会在编码是提示错误和校验,而第一种语法方式,只有在运行中才能知道是否会产生错误。


五、MyBatis标签

select标签

insert标签

update标签

delete标签

标签的常用属性

id 绑定接口方法

parameterType 传递进来的参数类型

resultType 返回的参数类型

resultMap 实体类属性与数据库字段的映射

传递参数的方式

1.使用注解进行传参。

2.使用Map进行传参。

3.使用JavaBean进行传参。

三种传参方式的区别:

使用 Map 传递参数会导致业务可读性的丧失,继而导致后续扩展和维护的困难,所以在实际应用中我们应该果断废弃该方式。
使用 @Param 注解传递参数会受到参数个数的影响。当 n≤5 时,它是最佳的传参方式,因为它更加直观;当 n>5 时,多个参数将给调用带来困难。
当参数个数大于 5 个时,建议使用 JavaBean 方式。

六、resultMap元素

MyBatis中最复杂的元素,主要用于解决实体类属性名与数据库表中字段名不一致的情况,可以将查询结果映射成实体对象。

结构:

<resultMap id="" type="">
    <constructor>
        <idArg/>
        <arg/> 
    constructor>
    <id/>
    <result/>
    <association property=""/>
    <collection property=""/>
    <discriminator javaType="">
        <case value=""/>
    discriminator>
resultMap>

resultType与resultMap的区别:

本质上,MyBatis的每一个查询映射的返回类型都是resultMap,只是当我们提供的返回类型是 resultType时,MyBatis会自动把对应的值赋给resultType所指定对象的属性,而当我们提供的返回类型是resultMap时,MyBatis会将数据库中的列数据复制到对象的相应属性上,可用于复制查询。


七、关联(级联)查询

一对一级联:

通过  元素的子元素  处理一对一级联关系。

两种实现方式:

1.分步查询,通过两次或多次查询,为一对一关系的实体 Bean 赋值。

2.单步查询,通过关联查询实现。

一对多级联:

通过  元素的子元素  处理一对多级联关系,collection 可以将关联查询的多条记录映射到一个 list 集合属性中。

两种实现方式:

1.分步查询,通过两次或多次查询,为一对一关系的实体 Bean 赋值。

2.单步查询,通过关联查询实现。

多对多级联:

MyBatis 没有实现多对多级联,推荐通过两个一对多级联替换多对多级联,以降低关系的复杂度,简化程序。

例如,一个订单可以有多种商品,一种商品可以对应多个订单,订单与商品就是多对多的级联关系。可以使用一个中间表(订单记录表)将多对多级联转换成两个一对多的关系。

借助一张中间表声明两者之间的关系,如:order(订单),product(商品)和 order_details(订单和商品中间表)。

级联的优点是获取关联数据十分便捷。但是级联过多会增加系统的复杂度,同时降低系统的性能,此增彼减。所以记录超过 3 层时,就不要考虑使用级联了,因为这样会造成多个对象的关联,导致系统的耦合、负载和难以维护。


八、动态SQL

if标签:条件判断

<if test="判断条件">
    SQL语句
if>

choose、when和otherwise标签

choose 标签按顺序判断其内部 when 标签中的判断条件是否成立,如果有一个成立,则执行相应的 SQL 语句,choose 执行结束;如果都不成立,则执行 otherwise 中的 SQL 语句。这类似于 Java 的 switch 语句,choose 为 switch,when 为 case,otherwise 则为 default。

<choose>
    <when test="判断条件1">
        SQL语句1
    when >
    <when test="判断条件2">
        SQL语句2
    when >
    <when test="判断条件3">
        SQL语句3
    when >
    <otherwise>
        SQL语句4
    otherwise>
choose>

where标签

用来简化 SQL 语句中的条件判断,可以自动处理 AND/OR 条件。

if 语句中判断条件为 true 时,where 关键字才会加入到组装的 SQL 里面,否则就不加入。where 会检索语句,它会将 where 后的第一个 SQL 条件语句的 AND 或者 OR 关键词去掉。

<where>
    <if test="判断条件">
        AND/OR ...
    if>
where>

set标签

set 标签可以为 SQL 语句动态的添加 set 关键字,剔除追加到条件末尾多余的逗号

 <update id="updateStudent"
        parameterType="xxx.xxx.po.Student">
        UPDATE website
        <set>
            <if test="name!=null">name=#{name}if>
            <if test="age!=null">age=#{age}if>
        set>
        WHERE id=#{id}
    update>

foreach标签

<foreach item="item" index="index" collection="list|array|map key" open="(" separator="," close=")">
    参数值
foreach>
item:表示集合中每一个元素进行迭代时的别名。
index:指定一个名字,表示在迭代过程中每次迭代到的位置。
open:表示该语句以什么开始(既然是 in 条件语句,所以必然以(开始)。
separator:表示在每次进行迭代之间以什么符号作为分隔符(既然是 in 条件语句,所以必然以,作为分隔符)。
close:表示该语句以什么结束(既然是 in 条件语句,所以必然以)开始)。

bind标签

数据库的拼接函数或连接符号

<select id="selectStudent" resultType="xxx.xxx.po.Student">
    <bind name="pattern" value="'%'+_parameter+'%'" />
    SELECT id,name,sex,age,country
    FROM student
    WHERE name like #{pattern}
select>

trim标签

一般用于去除 SQL 语句中多余的 AND 关键字、逗号,或者给 SQL 语句前拼接 where、set 等后缀,可用于选择性插入、更新、删除或者条件查询等操作。

<trim prefix="前缀" suffix="后缀" prefixOverrides="忽略前缀字符" suffixOverrides="忽略后缀字符">
    SQL语句
trim>

九、分页功能

前端传入起始位置与页面容量参数。

limit #{from},#{pageSize}

起始位置下标=(页码-1)*页面容量。


十、缓存(一级缓存和二级缓存)

MyBatis 提供了一级缓存和二级缓存的支持。默认情况下,MyBatis 只开启一级缓存。

一级缓存是基于 PerpetualCache(MyBatis自带)的 HashMap 本地缓存,作用范围为 session 域内。当 session flush(刷新)或者 close(关闭)之后,该 session 中所有的 cache(缓存)就会被清空。

二级缓存是全局缓存,作用域超出 session 范围之外,可以被所有 SqlSession 共享。
一级缓存缓存的是 SQL 语句,二级缓存缓存的是结果对象。

十一、逆向工程

这里不做赘述,在mybatis-plus有更好的方式。

相关