文章目录
  1. 1. 接口绑定方案
    1. 1.1. mybatis如何通过接口查找对应的mapper.xml及方法执行详解
    2. 1.2. mybatis中接口文件Mapper和接口配置文件Mapper.xml不在同一个目录下
    3. 1.3. 通过接口绑定解决多参数的传递
  2. 2. 动态SQL
    1. 2.1. if标签
    2. 2.2. where 标签
    3. 2.3. choose,when,otherwise标签
    4. 2.4. Set标签
    5. 2.5. Trim标签
    6. 2.6. bind标签
    7. 2.7. foreach标签
    8. 2.8. sql,include标签
  3. 3. MyBatis的缓存机制
    1. 3.1. 一级缓存
    2. 3.2. 二级缓存
  4. 4. 解决列名和属性名不一致问题
    1. 4.1. 列别名
    2. 4.2. 使用\<resultMap>
  5. 5. 多表查询
    1. 5.1. resultMap的N+1方式实现多表查询(多对一)
    2. 5.2. 关联查询
    3. 5.3. resultMap的N+1方式实现多表查询(一对多)
    4. 5.4. resultMap的关联方式实现多表查询(一对多)
    5. 5.5. 通过Auto-Mapping实现多表查询(多对一)
  6. 6. 注解开发
  7. 7. MyBatis运行原理
    1. 7.1. 运行过程中涉及到的类或接口
    2. 7.2. 描述

接口绑定方案

MyBatis中,提供了一套接口绑定方案,程序员可以提供一个接口,然后提供对应接口的一个mapper.xml文件。

MyBatis会自动将接口和xml文件进行绑定,实际上就是MyBatis会根据接口和对应的xml文件创建接口的实现类。

可以得到实现类的对象。

实现:

映射文件的命名和接口的命名一致

映射文件的namespace写接口的全限定路径

Mapper接口与Mapper.xml放在同一个包下

mybatis如何通过接口查找对应的mapper.xml及方法执行详解

链接:https://www.jb51.net/article/116402.htm

mybatis中接口文件Mapper和接口配置文件Mapper.xml不在同一个目录下

1:只有单独的Mybatis没有Spring的情况下

a:首先修改*Mapper.xml中的namespace

1
<mapper namespace="cn.gsm.mkm.dao.UserMapper">

指定到你的*Mapper接口

b:在mybatis总配置文件中指定扫描目标

<mappers>
    <mapper resource="cn/gsm/mkm/mapper/UserMapper.xml"></mapper>
    <package name="cn.gsm.mkm.dao.UserMapper"></package><!-- 指定具体文件-->
</mappers>

需要注意,这样配置必须指定具体的文件。否则dom4j解析会报错SAXParseException。

通过接口绑定解决多参数的传递

1)接口中定义方法

1
User selByUP(String username, String password);

映射文件中提供对应的标签. 此时, SQL语句中获取方式

有两种, 通过#{index}或#{param+数字}的方式.

1
2
3
4
5
<select id=*"selByUP"* resultType=*"user"*> 

select * from t_user where username=#{0} and password=#{1}

</select>

2) 接口中定义方法, 参数中使用@Param 注解设定参数名用

于在 SQL 语句中使用.

1
User selByUP(@Param("username") String username, @Param("password") String password);

映射文件中提供对应的标签. 此时, SQL语句中获取方式

有两种, 通过#{参数名称}或#{param+数字}的方式.

1
2
3
4
5
6
7
<select id=*"selByUP"* resultType=*"user"*> 

select * from t_user where username=#{username} and

password=#{password}

</select>

动态SQL

根据条件的不同, SQL 语句也会随之动态的改变. MyBatis 中, 提供了一组标签用于实现动态 SQL.

if标签

用于进行条件判断, test 属性用于指定判断条件. 为了拼接 条件, 在 SQL 语句后强行添加 1=1 的恒成立条件.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<select id=*"sel"* resultType=*"user"*> 

select * from t_user where 1=1

<if test=*"username != null and username != ''"*>

and username=#{username}

</if>

<if test=*"password != null and password != ''"*>

and password=#{password}

</if>

</select>

if标签中的test属性中取值直接写别名,不能用索引或者param+数字取值,也不用#{别名}

1
2
3
4
5
<!-- 5.判断字符串是否等于特定字符(比如此处的user) -->
<if test='stringParam != null and stringParam == "user"'></if>
<if test="stringParam != null and stringParam != 'user'"></if>
<!-- 如果要用这个写法要 -->
<if test="stringParam != null and stringParam != 'user'.toString()"></if>

where 标签

用于管理 where 子句. 有如下功能:

a)如果没有条件, 不会生成 where 关键字

b)如果有条件, 会自动添加 where 关键字

c)如果第一个条件中有 and, 去除之

1
2
3
4
5
6
7
8
9
10
11
<select id="sel" resultType="user">
select * from t_user
<where>
<if test="username != null and username != ''">
and username=#{username}
</if>
<if test="password != null and password != ''">
and password=#{password}
</if>
</where>
</select>

choose,when,otherwise标签

这是一套标签, 功能类似于 switch…case…default

when只成立一个

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<select id=*"sel"* resultType=*"user"*> 

select * from t_user

<where>
<choose>
<!-- when 只成立一个-->
<when test=*"username != null and username != ''"*>
and username = #{username}
</when>
<when test=*"password != null and password != ''"*>
and password = #{password}
</when>
<otherwise>
and 1=1
</otherwise>
</choose>
</where>
</select>

Set标签

用于维护 update 语句中的 set 子句. 功能如下:

a)满足条件时, 会自动添加 set 关键字

b)会去除 set 子句中多余的逗号

c)不满足条件时, 不会生成 set 关键字

Trim标签

用于在前后添加或删除一些内容

a)prefix, 在前面添加内容

b)prefixOverrides, 从前面去除内容

c)suffix, 向后面添加内容

d)suffixOverrides, 从后面去除内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<update id=*"updUser"* parameterType=*"user"*> 
update t_user
<!--
prefix: 前缀, 表示向前面添加内容
prefixOverrides: 从前面删除内容
suffix: 后缀, 表示向后面添加内容
suffixOverrides: 从后面删除内容
-->
<trim prefix=*"set"* prefixOverrides=*"user"* suffix=*"hahaha"*
suffixOverrides=*","*>
username=#{username},
</trim>
where id=#{id}
</update>

bind标签

用于对数据进行再加工, 用于模糊查询

1
2
3
4
5
6
7
8
9
10
<select id="sel" resultType="user">
select * from t_user
<where>
<if test="username!=null and username!=''">
<!-- 处理username,将值处理后依旧赋值给username -->
<bind name="username" value="'%' + username + '%'"/>
and username like #{username}
</if>
</where>
</select>

foreach标签

用于在 SQL 语句中遍历集合参数, 在 in 查询中使用

a)collection: 待遍历的集合

b)open: 设置开始符号

c)item: 迭代变量

d)separator: 项目分隔符

e)close: 设置结束符号

1
2
3
4
5
6
7
8
9
10
<select id="selIn" parameterType="list" resultType="user">
select * from t_user where id in
<!--collection="list" 指定集合是list-->
<foreach collection="list" open="(" separator="," close=")"
item="item">
#{item}
</foreach>
</select>
//接口中起别名list
List<User> selIn(@Param("list") List<Integer> list);

sql,include标签

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<sql>用于提取 SQL 语句, <include>用于引用 SQL 语句


<sql id="mySql">
id, username, password
</sql>

<select id="selIn" parameterType="list" resultType="user">
select
<!--引用提取的sql语句-->
<include refid="mySql"/>
from t_user where id in
<foreach collection="list" open="(" separator="," close=")"
item="item">
#{item}
</foreach>
</select>

MyBatis的缓存机制

a)缓存用于提高查询的效率.

b)MyBatis的缓存是使用SQL标签的. 执行相同的标签可以使用缓缓存.

c) MyBatis 中有两种缓存机制.

注意:缓存的查询通过id标识,即同一个sql语句(namespace+id)

一级缓存

a)默认开启. 线程级别的缓存, SqlSession 的缓存

b)在一个 SqlSession 生命周期中有效. SqlSession 关闭,

缓存清空.sqlSession对象级别的

二级缓存

a)进程级别的缓存, SqlSessionFactory 的缓存

b)在一个 SqlSessionFactory 生命周期中有效.可以在多个

SqlSession 生命中期中共享.

c)默认关闭, 需要使用的时候, 要为某个命名空间开启二级

缓存(在 mapper.xml 中配置\<cache>.

1
2
<!-- 开启二级缓存, 要求实体类进行序列化 -->
<cache />
1
2
<!--readOnly只读,实体类可以不实现序列化接口-->
<cache readOnly="true"></cache>

解决列名和属性名不一致问题

如果查询时使用 resultType 属性, 表示采用 MyBatis 的 Auto-Mapping(自动映射)机制, 即相同的列名和属性名会自

动匹配. 因此, 当数据库表的列名和类的属性名不一致时, 会导致查不到数据. 解决该问题可以有两种方式:

列别名

查询时, 可以通过列别名的方式将列名和属性名保持一致, 继续使用自动映射, 从而解决该问题. 但是较为麻烦.

1
2
3
<select id="selAll" resultType="user">
select id id1, username username1, password password2 from t_user
</select>

使用\<resultMap>

\<resultMap>用于自定义映射关系, 可以由程序员自主制定 列名和属性名的映射关系. 一旦使用 resultMap, 表示不再

采用自动映射机制.

1
2
3
4
5
6
7
8
9
10
11
<!--type实体类,id标识该resultMap-->
<resultMap type=*"user"* id=*"umap"*>
<!-- id用于映射主键 -->
<id column=*"id"* property=*"id1"* />
<!-- 非主键使用result映射 -->
<result column=*"username"* property=*"username1"* />
<result column=*"password"* property=*"password1"* />
</resultMap>
<select id=*"selAll"* resultMap=*"umap"*>
select * from t_user
</select>

多表查询

resultMap的N+1方式实现多表查询(多对一)

resultMap中的association属性用于关联一个对象

1) property: 指定要关联的属性名

2) select: 设定要继续引用的查询, namespace+id

3) column: 查询时需要传递的列

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<resultMap type="Student" id="stumap">
<!-- id用于映射主键 -->
<id column="s_id" property="id"/>
<!-- 非主键使用result映射 -->
<result column="s_name" property="name"/>
<result column="s_age" property="age"/>
<result column="s_gender" property="gender"/>
<result column="s_c_id" property="cid"/>
<!-- 用于关联一个对象
property:Student实体类中的属性
select:调用一个查询方法
column:使用哪一列的值作为参数传递到select调用的查询方法
注意:column使用数据库列名s_c_id
-->
<association property="clazz" select="com.szxy.mapper.ClazzMapper.selById" column="s_c_id"></association>
</resultMap>

关联查询

a)在 StudentMapper.xml 中定义多表连接查询 SQL 语句, 一 次性查到需要的所有数据, 包括对应班级的信息.

b)通过resultMap定义映射关系, 并通过association指 定对象属性的映射关系. 可以把association看成一个resultMap使用. javaType 属性表示当前对象, 可以写 全限定路径或别名.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<!-- 关联查询 -->
<resultMap type="Student" id="smap">
<id column="sid" property="id"/>
<result column="sname" property="name"/>
<result column="s_age" property="age"/>
<result column="s_gender" property="gender"/>
<result column="s_c_id" property="cid"/>
<!-- property:Student类的属性名
javaType:是一个类型,Clazz的类型,可以当做association的返回值类型
-->
<association property="clazz" javaType="Clazz">
<id column="id" property="id"/>
<result column="c_name" property="name"/>
<result column="c_room" property="room"/>
</association>
</resultMap>
<select id="selAll" resultMap="smap">
select s_id sid,s_name sname,s_age, s_gender,s_c_id cid,c_name cname,c_room
from t_student s
left join t_class c
on s.s_c_id = c_id
</select>

resultMap的N+1方式实现多表查询(一对多)

​ 提供 ClazzMapper 和 StudentMapper, ClazzMapper 查询所有

班级信息, StudentMapper 根据班级编号查询学生信息.

在 ClazzMapper 中使用\<collection>设置装配.

a)\<collection>用于关联一个集合

 property: 指定要关联的属性名

 select: 设定要继续引用的查询, namespace+id

 column: 查询时需要传递的列

1
2
3
4
5
6
7
8
9
10
11
<!-- N+1多对一查询 -->
<resultMap type="Clazz" id="cmap">
<id column="c_id" property="id"/>
<result column="c_name" property="name"/>
<result column="c_room" property="room"/>
<!-- 关联一个集合 -->
<collection property="stus" select="com.szxy.mapper.StudentMapper.selByCid" column="c_id"></collection>
</resultMap>
<select id="selAll" resultMap="cmap">
select * from t_class
</select>

resultMap的关联方式实现多表查询(一对多)

a)在 ClazzMapper.xml 中定义多表连接查询 SQL 语句, 一次 性查到需要的所有数据, 包括对应学生的信息.

b)通过\<resultMap>定义映射关系, 并通过\<collection>指 定集合属性泛型的映射关系. 可以把\<collection>看成一

个\<resultMap>使用. ofType 属性表示集合的泛型, 可以 写全限定路径或别名.

注:colletion关联一个集合

1)property: Clazz类中的stus属性名

2)javaType: Clazz类中的stus属性的类型

3)ofType:stus属性是List集合,指定泛型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<!-- 关联查询(多对一) -->
<resultMap type="Clazz" id="clzmap">
<id column="cid" property="id"/>
<result column="cname" property="name"/>
<result column="croom" property="room"/>
<!-- 关联一个集合
ofType:集合的泛型
-->
<collection property="stus" javaType="list" ofType="Student">
<id column="sid" property="id"/>
<result column="sname" property="name"/>
<result column="sage" property="age"/>
<result column="sgender" property="gender"/>
<result column="cid" property="cid"/>
</collection>
</resultMap>
<select id="selAll2" resultMap="clzmap">
select c.c_id cid,c.c_name cname, c_room croom,s.s_id sid, s.s_name sname,s.s_age sage,s.s_gender sgender
from t_class c
left join t_student s
on c.c_id = s.s_c_id
</select>

通过Auto-Mapping实现多表查询(多对一)

a)通过 MyBatis 的 Auto-Mapping 机制及数据库查询时的别 名结合, 可以方便的实现多表查询.

b)SQL 语句中, 别名出现特殊符号时, 必须进行处理. MySQL 可以使用()符号, Oracle 可以使用(“”)符号.

1
2
3
4
5
6
7
8
9
<!-- AutoMapping
将别名使用属性名.属性来进行自动映射
-->
<select id="selAutoMapping" resultType="Student">
select s_id id,s_name name,s_age age,s_gender gender,s_c_id cid,s_c_id `clazz.id`,c_name `clazz.name`,c_room `clazz.room`
from t_student s
left JOIN t_class c
on s.s_c_id = c.c_id
</select>

注解开发

a)注解是用于描述代码的代码. 例如: @Test(用于描述方法

进行 junit 测试), @Override(用于描述方法的重写), @Param(用于描述属性的名称)

b)注解的使用风格: @xxx(属性), 使用前必须先导包

c)使用注解一般用于简化配置文件. 但是, 注解有时候也不 是很友好(有时候反而更麻烦), 例如动态 SQL.

d)关于注解的属性

 属性的设定方式是: 属性名=属性值

e)关于属性值的类型

 基本类型和 String, 可以直接使用双引号的形式

 数组类型, name={值 1, 值 2, …}; 如果数组元素只有

一个, 可以省略大括号

 对象类型, name=@对象名(属性)

 如果属性是该注解的默认属性, 而且该注解只配置这

一个属性, 可以将属性名省略

f)注解和配置文件可以配合使用

1
2
3
4
5
6
7
8
9
10
11
@Select("select * from t_student")
List<Student> selAll();

@Insert(value = {"insert into t_student values(default,#{name},#{age},#{gender},#{cid})"})
int insStu(Student student);

@Update(value = {"update t_student set s_age = #{age} where s_id = #{0}"})
int updStu(int id, @Param("age")int age);

@Delete("delete from t_student where s_id = #{0}")
int delStu(int id);

其他注解

1
2
3
4
5
6
7
@Results: 类似于<resultMap> 

@Result: 类似于<resultMap>的子标签

@One: 类似于<association>

@Many: 类似于<collection>

@One

1
2
3
4
5
6
7
8
9
10
11
12
13
14
  //N+1查询
@Select("select * from t_student")
@Results(value = {
@Result(column = "s_id", property = "id",id = true),
@Result(column = "s_name", property = "name"),
@Result(column = "s_age", property = "age"),
@Result(column = "s_gender", property = "gender"),
@Result(column = "s_c_id", property = "cid"),
@Result(property = "clazz",
one = @One(select = "com.szxy.mapper.ClazzMapper.selById"),
column = "s_c_id"
)
})
List<Student> sel();

@Many

1
2
3
4
5
6
7
8
9
10
11
@Select("select * from t_class")
@Results(value = {
@Result(column = "c_id", property = "id", id = true),
@Result(column = "c_name", property = "name"),
@Result(column = "c_room", property = "room"),
@Result(property = "stus",
many = @Many(select = "com.szxy.mapper.StudentMapper.selByCid"),
column = "c_id"
)
})
List<Clazz> selClz();

MyBatis运行原理

运行过程中涉及到的类或接口

1)Resources(C)

用于加载 MyBatis 核心配置文件

2)XMLConfigBuilder(C)

用于解析 xml 文件(核心配置文件)

3) Configuration(C)

用于存放 xml 文件解析后的结果

4)DefaultSqlSessionFactory(C)

是 SqlSessionFactory(I)的 实 现 类 , 创 建 时 需 要 使 用

Configuration 对象

5) SqlSession(I)

是 MyBatis 操作的核心

6)DefaultSqlSession(C)

是 SqlSession 接口的实现类

7) TransactionFactory(I)

用于生产 Transaction 对象

8) Transaction(I)

用于表示操作数据库的事务对象

9)Executor(I)

是 MyBatis 的核心执行器, 类似于 jdbc 中的 Statement, 常 用的实现类是 SimpleExecutor

描述

​ 当Mybatis运行开始时,先要通过Resources加载核心配置文件,之后使用XmlConfigBuilder对配置文件进行

解析,将解析结果封装为Configuration对象。接着,使用Configuration对象构建一个DefaultSqlSessionFactory

对象,至此,SqlSession工厂构建完成。

​ 接下来,通过工厂对象调用openSession方法创建SqlSession对象。在这个过程中,需要通过TransactionFactory

生产一个Transaction对象,并且,还需要创建核心执行器Executor对象。之后,通过这些对象来创建DefaultSqlSession对象,至此,SqlSession对象创建成功。

​ 之后,通过SqlSession对象执行相应的操作。如果执行成功,调用commit()方法提交事务;如果失败,调用rollback()方法进行事务回滚。最后,调用close()方法关闭SqlSession资源,以上,就是MyBatis的运行原理。

文章目录
  1. 1. 接口绑定方案
    1. 1.1. mybatis如何通过接口查找对应的mapper.xml及方法执行详解
    2. 1.2. mybatis中接口文件Mapper和接口配置文件Mapper.xml不在同一个目录下
    3. 1.3. 通过接口绑定解决多参数的传递
  2. 2. 动态SQL
    1. 2.1. if标签
    2. 2.2. where 标签
    3. 2.3. choose,when,otherwise标签
    4. 2.4. Set标签
    5. 2.5. Trim标签
    6. 2.6. bind标签
    7. 2.7. foreach标签
    8. 2.8. sql,include标签
  3. 3. MyBatis的缓存机制
    1. 3.1. 一级缓存
    2. 3.2. 二级缓存
  4. 4. 解决列名和属性名不一致问题
    1. 4.1. 列别名
    2. 4.2. 使用\<resultMap>
  5. 5. 多表查询
    1. 5.1. resultMap的N+1方式实现多表查询(多对一)
    2. 5.2. 关联查询
    3. 5.3. resultMap的N+1方式实现多表查询(一对多)
    4. 5.4. resultMap的关联方式实现多表查询(一对多)
    5. 5.5. 通过Auto-Mapping实现多表查询(多对一)
  6. 6. 注解开发
  7. 7. MyBatis运行原理
    1. 7.1. 运行过程中涉及到的类或接口
    2. 7.2. 描述