SSM-Mybatis框架学习
一、框架
1.1 什么是框架
框架(Framework)是整个或部分系统的可重用设计,表现为一组抽象构件及构件实例间交互的方法;另一种定义认为,框架是可被应用开发者定制的应用骨架。前者是从应用方面而后者是从目的方面给出的定义。
简而言之,框架其实就是某种应用的半成品,就是一组组件,供你选用完成你自己的系统。简单说就是使用别人搭好的舞台,你来做表演。而且,框架一般是成熟的,不断升级的软件。
2.2 MVC设计思想
什么是MVC?
M(Model模型)V(View视图)C(Controller控制器)开发模型
[图片上传失败...(image-f94c72-1624563186741)]
二、Mybatis 框架快速入门
2.1创建 maven 工程
创建 mybatis01 的工程,工程信息如下:
Groupid:com.itheima
ArtifactId:mybatis01
Packing:jar
2.2 添加 Mybatis3.4.5 的坐标
org.mybatis
mybatis
3.4.5
junit
junit
4.10
test
mysql
mysql-connector-java
5.1.6
runtime
log4j
log4j
1.2.12
2.3创建User实体类
2.4编写持久层接口UserDao(内部写方法)
2.5 编写持久层接口的映射文件 IUserDao.xml(SQL语句等配置信息)
2.6 编写 SqlMapConfig.xml 配置文件
文件创建位置如图所示:
[图片上传失败...(image-25132-1624563186741)]
2.7 编写测试类
在测试类中
//1.读取配置文件
InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");
//2.创建 SqlSessionFactory 的构建者对象
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
//3.使用构建者创建工厂对象 SqlSessionFactory
SqlSessionFactory factory = builder.build(in);
//4.使用 SqlSessionFactory 生产 SqlSession 对象
SqlSession session = factory.openSession();
//5.使用 SqlSession 创建 dao 接口的代理对象
IUserDao userDao = session.getMapper(IUserDao.class);
//6.使用代理对象执行查询所有方法
List users = userDao.findAll();
for(User user : users) {
System.out.println(user);
}
//7.释放资源
session.close();
in.close();
补充:
基于注解的mybatis使用
①在持久层的方法上添加Sql语句的注解如:
@Select("select * from user")
②修改SqlMapConfig.xml
"com.itheima.dao.IUserDao"/>
三、自定义 Mybatis 框架
实际开发中常使用mybatis代理jdbc所以在这里就不细说了
具体实现代码:
Silencoco/SSM-Mybatis: SSM 框架之Mybatis学习 (github.com)
设计说明:
[图片上传失败...(image-c949c4-1624563186740)]
[图片上传失败...(image-b172f5-1624563186740)]
[图片上传失败...(image-146c33-1624563186740)]
[图片上传失败...(image-726674-1624563186740)]
四、代理DAO实现CRUD操作
Mybatis 与 JDBC 编程的比较
1.数据库链接创建、释放频繁造成系统资源浪费从而影响系统性能,如果使用数据库链接池可解决此问题。解决:在 SqlMapConfig.xml 中配置数据链接池,使用连接池管理数据库链接。
2.Sql 语句写在代码中造成代码不易维护,实际应用 sql 变化的可能较大,sql 变动需要改变 java 代码。
解决:将 Sql 语句配置在 XXXXmapper.xml 文件中与 java 代码分离。
3.向 sql 语句传参数麻烦,因为 sql 语句的 where 条件不一定,可能多也可能少,占位符需要和参数对应。
解决:Mybatis 自动将 java 对象映射至 sql 语句,通过 statement 中的 parameterType 定义输入参数的类型。
4.对结果集解析麻烦,sql 变化导致解析代码变化,且解析前需要遍历,如果能将数据库记录封装成 pojo 对象解析比较方便。
解决:Mybatis 自动将 sql 执行结果映射至 java 对象,通过 statement 中的 resultType 定义输出结果的类型
五、 Mybatis 的输出结果封装
resultType 属性:
可以指定结果集的类型,它支持基本类型和实体类类型
同时,当是实体类名称是,还有一个要求,实体类中的属性名称必须和查询语句中的列名保持一致,否则无法实现封装。
resultMap 结果类型:
resultMap 标签可以建立查询的列名和实体类的属性名称不一致时建立对应关系。从而实现封装。
在 select 标签中使用 resultMap 属性指定引用即可。同时 resultMap 可以实现将查询结果映射为复杂类型的 pojo,比如在查询结果映射对象中包括 pojo 和 list 实现一对一查询和一对多查询。
六、SqlMapConfig.xml配置文件
-properties****(属性)**
--property
-settings(全局配置参数)
--setting
-typeAliases****(类型别名)
--typeAliase
--package
-typeHandlers(类型处理器)
-objectFactory(对象工厂)
-plugins(插件)
-environments(环境集合属性对象)
--environment(环境子属性对象)
---transactionManager(事务管理)
---dataSource(数据源)
-mappers****(映射器)
--mapper
--package
properties****(属性)的两种配置方式
一、
二、在 classpath 下定义 db.properties 文件
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/eesy
jdbc.username=root
jdbc.password=1234
dataSource 标签就变成了引用下面的配置
6.1 typeAliases(类型别名)
在 SqlMapConfig.xml 中配置:
6.2 mappers(映射器)
6.2.1
使用相对于类路径的资源
如:
6.2.2
使用 mapper 接口类路径
如:
注意:此种方法要求 mapper 接口名称和 mapper 映射文件名称相同,且放在同一个目录中。
6.2.3
注册指定包下的所有 mapper 接口
如:
注意:此种方法要求 mapper 接口名称和 mapper 映射文件名称相同,且放在同一个目录中。
七、Mybatis 连接池与事务深入
在 Mybatis 的 SqlMapConfig.xml 配置文件中,通过
我们的数据源配置就是在 SqlMapConfig.xml 文件中,具体配置如下:
MyBatis 在初始化时,根据
type=”POOLED”:MyBatis 会创建 PooledDataSource 实例
type=”UNPOOLED” : MyBatis 会创建 UnpooledDataSource 实例
type=”JNDI”:MyBatis 会从 JNDI 服务上查找 DataSource 实例,然后返回使用
7.1 Mybatis 的事务控制
在 JDBC 中我们可以通过手动方式将事务的提交改为手动方式,通过 setAutoCommit()方法就可以调整。 那么我们的 Mybatis 框架因为是对 JDBC 的封装,所以 Mybatis 框架的事务控制方式,本身也是用 JDBC 的setAutoCommit()方法来设置事务提交方式的。
session.commit();
7.1.1 Mybatis 自动提交事务的设置
通过上面的研究和分析,现在我们一起思考,为什么 CUD 过程中必须使用 sqlSession.commit()提交事务?主要原因就是在连接池中取出的连接,都会将调用 connection.setAutoCommit(false)方法,这样我们就必须使用 sqlSession.commit()方法,相当于使用了 JDBC 中的 connection.commit()方法实现事务提交.
//1.读取配置文件
in = Resources.getResourceAsStream("SqlMapConfig.xml");
//2.创建构建者对象
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
//3.创建 SqlSession 工厂对象
factory = builder.build(in);
//4.创建 SqlSession 对象
session = factory.openSession(true);
//5.创建 Dao 的代理对象
userDao = session.getMapper(IUserDao.class);
8. Mybatis 的动态 SQL 语句
持久层:
测试类
@Test
public void testFindByUser() {
User u = new User();
u.setUsername("%王%");
u.setAddress("%顺义%");
//6.执行操作
List < User > users = userDao.findByUser(u);
for (User user: users) {
System.out.println(user);
}
}
9. Mybatis 中简化编写的 SQL 片段
select * from user
八、Mybatis 多表查询之一对多、多对多
一对多:
需求:
查询所有用户信息及用户关联的账户信息。
分析:
用户信息和他的账户信息为一对多关系,并且查询过程中如果用户没有账户信息,此时也要将用户信息查询出来,我们想到了左外连接查询比较合适。
多对多:
通过前面的学习,我们使用 Mybatis 实现一对多关系的维护。多对多关系其实我们看成是双向的一对多关系
九、 Mybatis 延迟加载策略
9.1 什么是延迟加载
延迟加载:
就是在需要用到数据时才进行加载,不需要用到数据时就不加载数据。延迟加载也称懒加载.
好处:
先从单表查询,需要时再从关联表去关联查询,大大提高数据库性能,因为查询单表要比关联查询多张表速度要快。
坏处:
因为只有当需要用到数据时,才会进行数据库查询,这样在大批量数据查询时,因为查询工作也要消耗时间,所以可能造成用户等待时间变长,造成用户体验下降。
9.2 实现需求
需求:
查询账户(Account)信息并且关联查询用户(User)信息。如果先查询账户(Account)信息即可满足要求,当我们需要查询用户(User)信息时再查询用户(User)信息。把对用户(User)信息的按需去查询就是延迟加载。mybatis第三天实现多表操作时,我们使用了resultMap来实现一对一,一对多,多对多关系的操作。主要是通过 association、collection 实现一对一及一对多映射。association、collection 具备延迟加载功能。
9.3 使用 assocation 实现延迟加载
select="com.itheima.dao.IUserDao.findById"
column="uid">
select: 填写我们要调用的 select 映射的 id column : 填写我们要传递给 select 映射的参数
持久层接口及映射文件
public interface** IUserDao {
/**
* 根据 id 查询
* @param userId
* @return
*/
User findById(Integer userId);
}
"1.0" encoding="UTF-8"?>
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
"com.itheima.dao.IUserDao">
select * from user where id = #{uid}
9.4 开启延迟加载
9.5 使用 Collection 实现延迟加载
同样我们也可以在一对多关系配置的
在 User 实体类中加入 List
编写用户和账户持久层接口的方法
编写用户持久层映射配置
select="com.itheima.dao.IAccountDao.findByUid"
column="id">
十、Mybatis 一级缓存
一级缓存是 SqlSession 级别的缓存,只要 SqlSession 没有 flush 或 close,它就存在。
一级缓存是 SqlSession 范围的缓存,当调用 SqlSession 的修改,添加,删除,commit(),close()等方法时,就会清空一级缓存。
第一次发起查询用户 id 为 1 的用户信息,先去找缓存中是否有 id 为 1 的用户信息,如果没有,从数据库查询用户信息。得到用户信息,将用户信息存储到一级缓存中。
如果 sqlSession 去执行 commit 操作(执行插入、更新、删除),清空 SqlSession 中的一级缓存,这样做的目的为了让缓存中存储的是最新的信息,避免脏读。
第二次发起查询用户 id 为 1 的用户信息,先去找缓存中是否有 id 为 1 的用户信息,缓存中有,直接从缓存中获取用户信息。
十一、二级缓存的开启与关闭
第一步:在 SqlMapConfig.xml 文件开启二级缓存
"cacheEnabled" value="true"/>
因为 cacheEnabled 的取值默认就为 true,所以这一步可以省略不配置。为 true 代表开启二级缓存;为false 代表不开启二级缓存。
第二步:配置相关的 Mapper 映射文件
配置 statement 上面的 useCache 属性
将 UserDao.xml 映射文件中的
二级缓存,如果不使用二级缓存可以设置为 false。
注意:针对每次查询都需要最新的数据 sql,要设置成 useCache=false,禁用二级缓存。
十二、 Mybatis 注解开发
12.1 mybatis 的常用注解说明
@Insert:实现新增
@Update:实现更新
@Delete:实现删除
@Select:实现查询
@Result:实现结果集封装
@Results:可以与@Result 一起使用,封装多个结果集
@ResultMap:实现引用@Results 定义的封装
@One:实现一对一结果集封装
@Many:实现一对多结果集封装
@SelectProvider: 实现动态 SQL 映射
@CacheNamespace:实现注解二级缓存的使用
12.2 使用注解实现复杂关系映射开发
实现复杂关系映射之前我们可以在映射文件中通过配置
助@Results 注解,@Result 注解,@One 注解,@Many 注解。