Mybatis 工作流程
1. 读取配置文件:mybatis-config.xml 为 Mybatis 的全局配置文件,配置了 Mybatis 的运行环境等信息,例如数据库连接信息。
2. 加载映射文件:映射文件即 SQL 映射文件,该文件中配置了操作数据库的 SQL 语句,需要在 MyBatis 配置文件 mybatis-config.xml 中加载。mybatis-config.xml 文件可以加载多个映射文件,每个文件对应数据库中的一张表。
3. 构造会话工厂:通过 Mybatis 的环境等配置信息构建会话工厂SqlSessionFactory。
4. 创建会话对象:由会话工厂创建 SqlSession 对象,该对象中包含了执行 SQL 语句的所有方法。
5. Executor 执行器:Mybatis 底层定义了一个 Executor 接口来操作数据库,它将根据 SqlSession 传递的参数动态地生成需要执行的 SQL 语句,同时负责查询缓存的维护。
6. MappedStatement 对象: 在 Executor 接口的执行方法中有一个 MappedStatement 类型的参数,该参数是对映射信息的封装,用于存储要映射的 SQL 语句的 id、参数等信息。
7. 输入参数映射:输入参数类型可以是 Map、List 等集合类型,也可以是基本数据类型和 POJO 类型。输入参数映射过程类似于 JDBC 对 preparedStatement 对象设置参数的过程。
8. 输出结果映射:输出结果类型可以是 Map、 List 等集合类型,也可以是基本数据类型和 POJO 类型。输出结果映射过程类似于 JDBC 对结果集的解析过程。
Mybatis缓存
Mybatis中有一级缓存和二级缓存,默认情况下一级缓存是开启的,而且是不能关闭的。
1. 一级缓存是指 SqlSession 级别的缓存,当在同一个 SqlSession 中进行相同的 SQL 语句查询时,第二次以后的查询不会从数据库查询,而是直接从缓存中获取,一级缓存最多缓存1024 条 SQL。
2. 二级缓存是指可以跨 SqlSession 的缓存,是 mapper 级别的缓存,对于mapper 级别的缓存不同的sqlsession 是可以共享的。
一级缓存原理:
1. 第一次发出一个查询 sql,sql 查询结果写入 sqlsession 的一级缓存中。
2. 缓存使用的数据结构是一个 map。key:MapperID+offset+limit+Sql+所有的入参。
3. 用户信息同一个 sqlsession 再次发出相同的sql,就从缓存中取出数据。
4. 如果两次中间出现 commit 操作 (修改、添加、删除),本sqlsession 中的一级缓存区域全部清空,下次再去缓存中查询不到。所以要从数据库查询,从数据库查询到再写入缓存。
二级缓存原理:
1.二级缓存的范围是 mapper 级别(mapper同一个命名空间,Namespace),mapper 以命名空间为单位创建缓存数据结构,结构是 map。
2.mybatis 的二级缓存是通过CacheExecutor实现的。CacheExecutor其实是 Executor 的代理对象。
3.所有的查询操作,在 CacheExecutor 中都会先匹配缓存中是否存在,不存在则查询数据库。
4.key:MapperID+offset+limit+Sql+所有的入参。
5.具体使用需要配置:Mybatis 全局配置中启用二级缓存配置。
6.在对应的 Mapper.xml 中配置 cache 节点。
7.在对应的 select 查询节点中添加 useCache=true。
Mybatis接口绑定实现方式
1.通过注解绑定,就是在接口的方法上面加上 @Select、@Update等注解,里面包含Sql语句来绑定。
2.通过xml里面写SQL来绑定, 在这种情况下,要指定xml映射文件里面的namespace必须为接口的全路径名。
代理方式:JDK动态代理
建议:当Sql语句比较简单时候,用注解绑定, 当SQL语句比较复杂时候,用xml绑定。
Mybatis结果封装返回方式
1.第一种是使用<resultMap>标签,逐一定义列名和对象属性名之间的映射关系。
2.第二种是使用sql列的别名功能,将列别名书写为对象属性名,比如T_NAME AS NAME。
备注:Mybatis通过反射创建对象。使用反射给对象的属性逐一赋值并返回。
Mybatis分页原理
Mybatis使用RowBounds对象进行分页,它是针对ResultSet结果集执行的内存分页,而非物理分页,可以在sql内直接书写带有物理分页的参数来完成物理分页功能,也可以使用分页插件来完成物理分页。
分页插件可以参考:pageHelper、MybatisPlus。
分页插件的原理:就是使用MyBatis提供的插件接口,实现自定义插件。
1.在插件的拦截方法内,拦截待执行的SQL。
2.然后根据设置的dialect(方言)和设置的分页参数,重写生成带有分页语句的SQL。
3.执行重写后的SQL,从而实现分页。
手写数据库连接池
1.读取jdbc数据库配置信息
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/singerdb
jdbc.username=root
jdbc.password=123456
# 初始化连接数
jdbc.initSize=3
# 最大连接数
jdbc.maxSize=6
# 连接超时时间,10S
jdbc.timeout=100000
2.配置类DataSourceConfig读取配置文件
3.定义连接池类(创建默认连接数的连接,提供获取连接和归还连接方法)
3.1创建连接
conn = DriverManager.getConnection(config.getUrl(), config.getUsername(), config.getPassword());
3.2 获取连接
4.执行SQL
4.1.创建statement并执行SQL
Statement stmt = conn.createStatement();
int result = stmt.executeUpdate(sql);
4.2创建PreparedStatement并设置参数执行SQL
PreparedStatement pre = connection.prepareStatement(sql);
for (int j = 0; j < parameters.length; j++) {
preparedStatement.setObject(j + 1, parameters[j]);
}
ResultSet resultSet = pre.executeUpdate();
5.结果集映射
Mybatis-plus
MyBatis-Plus (opens new window)(简称 MP)是一个 MyBatis (opens new window)的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。
特性
无侵入:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑。
损耗小:启动即会自动注入基本 CURD,性能基本无损耗,直接面向对象操作,BaseMapper。
强大的 CRUD 操作:内置通用 Mapper、通用 Service,仅仅通过少量配置即可实现单表大部分 CRUD 操作,更有强大的条件构造器,满足各类使用需求,简单的CRUD操作不用自己编写。
支持 Lambda 形式调用:通过 Lambda 表达式,方便的编写各类查询条件,无需再担心字段写错。
支持主键自动生成:支持多达 4 种主键策略(内含分布式唯一 ID 生成器 - Sequence),可自由配置,完美解决主键问题。
支持 ActiveRecord 模式:支持 ActiveRecord 形式调用,实体类只需继承 Model 类即可进行强大的 CRUD 操作。
支持自定义全局通用操作:支持全局通用方法注入( Write once, use anywhere )。
内置代码生成器:采用代码或者 Maven 插件可快速生成 Mapper 、 Model 、 Service 、 Controller 层代码,支持模板引擎,更有超多自定义配置等您来使用(自动生成代码)。
内置分页插件:基于 MyBatis 物理分页,开发者无需关心具体操作,配置好插件之后,写分页等同于普通 List 查询。
分页插件支持多种数据库:支持 MySQL、MariaDB、Oracle、DB2、H2、HSQL、SQLite、Postgre、SQLServer 等多种数据库。
内置性能分析插件:可输出 SQL 语句以及其执行时间,建议开发测试时启用该功能,能快速揪出慢查询。
内置全局拦截插件:提供全表 delete 、 update 操作智能分析阻断,也可自定义拦截规则,预防误操作。