1. 概念

MyBatis是一款优秀的基于ORM的半自动轻量级持久层框架,它支持定制化SQL、存储过程以及高级映射,使用XML或注解实现映射对应,结果集自动转换成指定类型,无需自己处理。

1.1 什么是ORM

ORM全称Object/Relation Mapping:表示对象-关系映射的缩写,它完成面向对象的编程语言到关系数据库的映射。
采用ORM框架后,应用程序不再直接访问底层数据库,而是以面向对象的方式来操作持久化对象,而ORM框架则将这些面向对象的操作转换成底层SQL操作。
ORM框架实现的效果:把对持久化对象的保存、修改、删除等操作,转换为对数据库的insert、update、delete操作。

1.2 什么是半自动

简单来说,半自动就是还需要开发人员自己写核心的SQL。
与之对应的就是全自动,类似Hibernate等,就是无需写SQL都是全自动完成。

2. 配置文件

Mybatis的配置文件一般分为两种,一个是核心配置文件,一个是映射配置文件,
核心配置文件配置了Mybatis的核心配置,包括数据库连接信息、是否开启缓存等;
映射配置文件主要是用于配置具体的映射关系的文件;

2.1 核心配置文件

Mybatis的核心配置文件一般我们命名为sqlMapConfig.xml,里面配置了相关的标签,来指定一些操作(标签是存在顺序的,如果顺序写错,会有提示),具体概述如下:

  • <configration/>:顶层配置标签
  • <properties/>:加载额外配置的properties文件
  • <setting/>:全局配置,例如是否使用缓存、超时时间设置等
  • <typeAliases/>:类型别名,给parameterType或者ResultType定义别名
  • <typeHandlers/>:类型处理器,配置将sql返回的数据库类型转换为相应Java类型的处理器
  • <objectFactory/>:对象工厂,可以继承DefaultObjectFactory来定义对象工厂
  • <plugins/>:插件,其实就是拦截器,通过实现Interceptor接口,并添加Intercepts注解(里面可以定义多个signature去拦截多个方法)
  • <environments/>:环境,里面可以定义多个环境变量(环境变量中可以指定事务、数据源等信息),由default来指定默认使用那个
  • <databaseIdProvider/>:数据库厂商标识
  • <mappers/>:需要加载的映射配置文件(可以通过package或者resource、url、class来加载一个或多个映射配置文件)

2.2 映射配置文件

在映射配置文件中,常用的标签如下:

  • <resultMap/>来指定数据库字段名和实体类属性的对应关系。
  • <parameterType/>:参数类型
  • <resultType/>或<resultMap/>:结果类型或者使用的结果集
  • <select/> <insert/> <update/> <delete/>:定义增删改查的SQL语句

常用的动态标签:

  • where:使用该标签会自动去除第一个and,不需要写where 1=1
  • if:根据参数对象的取值进行不同条件的判断
  • foreach:进行数组的循环,通过open和close属性,生成类似 id in ()或者对map进行遍历
  • include:进行SQL片段抽取,避免同样的SQL的重复编写
  • choose、when、otherwise:进行条件判断,如果不符合就是要otherwise(相当于default)

3. 复杂映射

复杂映射,主要是为了解决一对一、一对多、多对多的映射关系

2.1 一对一

在此举例说明,现有两张表,一张用户表User,一张省信息表province。
一个人属于一个省,当查询User信息时,也要将所属的省信息查出,这时就符合所说的一对一映射查询。
如果通过SQL完成查询,对应的sql语句应该是:

1
select u.name, p.pname from province p,user u where u.pid=p.pid;

反应在Java实体上,就是User类中,会声明一个Province的对象:

1
2
3
4
5
6
public class User {
private Long uid;
private String name;
private Province province;
........
}

现在如果通过XML方式想要在查询用户时将省信息同时查出,需要用到<association/>标签。UserMapper.xml中的resultMap需要增加如下配置:

1
2
3
4
5
6
7
8
9
<resultMap id="userMap" type="com.jfl.test.User">
<result property="id" column="id"></result>
<result property="name" column="name"></result>
<!-- 声明一对一相关信息 -->
<association property="province" javaType="com.jfl.test.Province">
<result column="pid" property="pid"></result>
<result column="pname" property="pname"></result>
</association>
</resultMap>

其中<association/>的property属性对应实体中的属性名,里面的标签对应Province的属性。
此时查询结果就是如下:

1
User{id=1,name='tom',province=Province{pid=1,pname='beijing'}}

2.2 一对多

还是上面的例子,一个省对应多个人,这种情况下想要查询一对多,通过SQL查询的话,SQL语句如下:

1
select p.pid,p.pname,u.id,u.name from province p left join user u on u.pid=p.pid;

反应在Java实体上,就是Province类中,会声明一个List<User>的对象:

1
2
3
4
5
6
public class Province {
private Long pid;
private String pname;
private List<User> userList;
........
}

而mybatis的映射配置XML文件中,需要增加<collection />配置,才可以支持一对多:

1
2
3
4
5
6
7
8
<resultMap id="provinceMap" type="com.jfl.test.Province">
<result column="pid" property="pid"></result>
<result column="pname" property="pname"></result>
<collection property="userList" ofType="com.jfl.test.User">
<result column="id" property="id"></result>
<result column="name" property="name"></result>
</collection>
</resultMap>

2.3 多对多

此处举例说明,一个学生学习多门课程,每门课程也有很多学生来学习。此时学生和课程的对应关系就是多对多,通常这种情况,在数据库设计时会通过中间表来实现,模型如下图:
在这里插入图片描述
此时就可以将学生和课程的多对多,看成是学生表和学生课程关系表的一对多;同理,课程和学生的关系,也可以看成是课程表和学生课程关系表的一对多。
所以多对多,其实就是两个一对多,具体实现参考一对多。