一、SQL映射器Mapper
- MyBatis基于代理机制,因此无需再编写Dao层的实现。
- 传统Dao接口,现在名称统一以Mapper结尾
- 两种实现方式:
- 传统的实现方式
- 映射器实现方式
- 使用映射器的步骤:
- 整体文件结构图
- 接口mapper
- 对应的mapper.xml文件
- 测试
- 使用mapper映射器的细节注意
- 根据需求,创建模型相关的Mapper接口。doaminMapper
- 编写映射文件。
(1)DomainMapper.xml的命名空间,必须和接口的“全限定名”一致。
(2)定义sql标签的id,需要和“mapper接口的方法”一致
- 总体流程图
二、MyBatis中的常用动态SQL
动态 SQL,mybatis的强大特性之一,解决根据不同条件拼接不同sql的麻烦
- 批量操作
(1)批量删除
-
批量删除的sql语句:
==delete from xxx where id in (3,2,…)==使用条件in即可批量删除 -
mybatis的核心配置文件:
-
映射文件
-
mapper接口中的方法
-
测试
(2)批量插入 -
批量插入的sql语句:
insert into xxx (name,age) values (“xx”,12),(“yy”,23)… 可以一直插入 -
mybatis的核心配置文件没变
-
映射文件。
-
mapper接口中的方法
-
测试
- 高级查询 if where
高级查询其实就是多条件查询。
- 准备一个query对象来接收前台传过来的参数值
Query最终通过Mapper的接口要传递到Mapper的配置文件中
(1)映射文件。
(2)mapper接口中的方法
(3)测试
- 结合query对象的高级查询的总条数查询
(1)映射文件
(2)mapper中的接口方法
(3)测试
- 解决更新时的数据丢失问题
问题描述;更新一条数据时,某些字段不需要更新,但是保存后,不需要更新的数据变成了null,没有保留原来的值,造成数据丢失。
解决:使用动态修改方式
(1)映射文件
(2)mapper接口的方法
(3)测试
三、结果映射(resultMap)
-
使用结果映射可以进行关联对象查询。
-
关联查询分类:
多对一:多个员工对应一个部门。一般在多方设计一个一方属性, 员工里面设计部门字段
一对一:一个员工只有一个身份证。随意一方设计一个字段
一对多:一个部门拥有多个员工。一方里面存放多方的一个集合
多对多: 一个员工有多个角色。一个角色属于多个员工。两方存放集合
在mybatis中只需要记住一对多和多对一即可,因为在mybatis中一对一的配置和多对一的配置是一模一样的,而且一对多和多对多的配置也是一模一样的 -
本质上:多对一,一对一是一样的,都只是 处理一个association。而一对多、多对多也是一样处理的都是集合(collection )
-
关联映射的处理方式
(1)嵌套结果:使用嵌套查询把所有结果一次查出。
(2)嵌套查询: 多次查询,合并结果
下面分别使用两种方式对多对一和一对多进行处理。
- 先准备好两张有关联的数据库表,准备好外键
部门表:
员工表:提供一个外键字段dept_id
两张表没有任何外键关联:
- 多对一的 嵌套结果 方案:多个员工对应一个部门
(1)mybatis的核心配置xml文件
(2)创建好两种表的domain
员工表domain:
部门表domain:
(3)在员工的mapper接口中
(4)在员工的映射文件中
(5)测试
(6)测试结果
- 分析:要两张表进行关联才会有值,但是字段又对应不上,一个是dept_id,另一个是department对象。
- 方案:将自动映射改为手动完成结果映射即可
解决问题:
- 在员工映射文件中配置手动映射和 association 标签
注意:使用了< association>标签自动映射会失效,表中的所有属性都要手动映射(如下:标签),否则的话没手动映射的字段只会打印出null值。
- 最后同样用findAll方法测试查询,显示结果为
问题:以上结果是错误的,部门名称成了员工的名字。
分析:映射文件中< association >标签配置的property的id确定是部门的id,但是后面column中的id不确定是谁的id。不确定是员工的id还是部门的id。
解决: 使用别名区分id - 在员工的映射文件中做别名的修改
- 展示效果:成功了
- 多对一的 嵌套查询 方案:
(1)在mybatis的核心配置文件中配置:
(2)在部门的映射文件中写一个根据部门id查询部门名称的sql语句
(3)在员工的映射文件中。
(4)打印结果:
(5)流程图:
- 多对一的 野方法 查询
最好是不要用,现在没有出问题,不代表以后不会出问题。慎重
- 只需要在员工的映射文件中使用野方法配置。
- 打印结果:
一对多的嵌套结果和嵌套查询方案如下:
- 首先,先准备好数据库表。
还是上面的两张数据库表 - 准备好domain。
员工domain:
部门domain:
- 在mybatis的核心xml配置文件中:
- 在部门的mapper接口中:
- 在部门的映射文件中:
- 测试:
- 问题:部门中员工为空值
- 分析:部门中根本就没有employees这个字段,所以要手动映射一下。
- 一对多的嵌套结果方案; 先用一条sql查出来再设置
- 更改下部门的映射文件
- 打印结果
- 问题。员工的名字成了部门的名字。
- 分析:原因和上面的多对一情况一样。分不清id字段属性员工还是部门
- 解决:还是==同样的使用别名-==来处理这一情况
在部门映射文件中设置字段别名以区分:注意左外连接
打印结果:成功
- 一对多 嵌套查询方案
根据部门id拿到所有的员工(员工中有部门的外键id)
- 在mybatis的核心xml配置文件中再引入员工的映射文件:
- 在员工的映射文件中:写一个根据外键(部门id)拿到员工信息的sql语句
- 在部门的映射文件中再根据员工的映射文件中的sql语句去查询员工。
- 打印效果
- 总结:流程跟上面的多对一的嵌套查询是一样的。只不过标签不同。
四、缓存
- 缓存概念:
以空间换时间”的策略。缓存其实就是把数据保存到内存中,以后直接从内存中获取,提高效率。 - Mybatis缓存
(1) 一级缓存:SqlSession级别缓存,缓存对象存储周期为第一次获取,到sqlsession被销毁掉,或是sqlSession().clearCache(); 这个缓存,我们一般不自己使用。mybatis自己查询的时候回使用,用来提高查询效率。
(2)二级缓存: SqlSessionFactory级别缓存,缓存对象存储周期为第一次获取,到SqlSessionFactory被销毁掉(应用停止了); 如果我们想要使用缓存就用它 - mybatis的一级缓存,SqlSession级别缓存步骤:
- 在mybatis的核心配置文件中引用映射文件
- 在映射文件中:写一条测试用的sql语句
- 在mapper接口中写一个对应映射文件的方法
- 测试:如果有缓存的话只会执行一条sql
- 打印结果
- mybatis的二级缓存,SqlSessionFactory级别缓存,步骤:
- 在以上的基础上。
- 在映射文件中加上标签即可有二级缓存
- 测试:只执行一条sql就代表有二级缓存
- 打印结果: