前言
之前阅读了JDK常用容器的源码本章就开始阅读Mybatis源码。不过在阅读之前我们首先搭建一下源码阅读环境,这样有利于我们后面的阅读,更加可以一边写注释一边的Debug。
MyBatis介绍
首先我们先介绍一下MyBatis是什么,如果你比较熟悉的话可以跳过前面的部分。本章主要概念
- 什么是Mybatis
- 为什么要用Mybatis
- 如何使用mybatis
- mybatis源码环境搭建
介绍
MyBatis 是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射。MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。同时Mybatis前身是 iBatis,iBatis 是 Apache 软件基金会下的一个开源项目。2010 年该项目从 Apache 基金会迁出,并改名为 MyBatis。同期,iBatis 停止维护。知道了这些之后我们就有一个问题,到底为什么要使用MyBatis
。
为什么用Mybatis
在实际的开发中我们可以使用JDBC来访问数据库,还可以使用Hibernate来访问我们的数据库,除此之外还有很多方案可以选择,那么我们为什么要使用Mybatis呢?我们使用JDBC和Mybatis拿来举个例子,来看一下各自的应用场景。本次项目地址‘’‘’‘’‘’‘’‘’‘’‘’‘’,这是已经整合的一套源码阅读环境,卡下来导入IDEA即可使用,同时本文中的例子也在项目中。
JDBC连接
创建数据库表
代码语言:javascript复制create table test.student (
id int(10),
name varchar(20),
primary key (id)
)
insert添加语句这里就不再贴了,读者可以自行添加数据。
使用JDBC我们就不使用Model类进行演示了,然后链接数据库执行sql语句
代码语言:javascript复制@Test
public void testJDBC(){
Connection conn = null;
Statement stmt = null;
try {
//加载驱动
Class.forName("com.mysql.jdbc.Driver");
conn = DriverManager.getConnection("jdbc:mysql://miniapp.lqcoder.com:3306/test","root","123456");
// 执行查询
stmt = conn.createStatement();
String sql;
sql = "select * from test.student";
ResultSet rs = stmt.executeQuery(sql);
// 展开结果集数据库
while(rs.next()){
// 通过字段检索
int id = rs.getInt("id");
String name = rs.getString("name");
// 输出数据
System.out.print("ID: " id);
System.out.print("名称: " name);
System.out.print("n");
}
// 完成后关闭
rs.close();
stmt.close();
conn.close();
} catch (ClassNotFoundException | SQLException e) {
e.printStackTrace();
}finally{
// 关闭资源
try{
if(stmt!=null) stmt.close();
}catch(SQLException se2){
}// 什么都不做
try{
if(conn!=null) conn.close();
}catch(SQLException se){
se.printStackTrace();
}
}
}
输出结果:
ID: 1名称: xiaomingID: 2名称: xiaozhang
使用Mybatis
由于我们这里是在源码中使用的查询所以不需要添加Mybatis依赖。首先创建mybatis的配置文件,新建一个mybatis-config.xml
文件,添加以下配置配置后期会详细解释,这里只做一个演示
,在下篇文章会详细的讲解整合SpringBoot
然后创建model
类,这里使用了lombok
来简化开发,可以自行了解一下。
创建mapper
文件
创建 dao
接口
然后在 mybatis-config.xml
配置文件中加入Mapper
Xml文件的路径
完整配置
然后创建测试方法
查询结果:
对比
接下来总结一下上面两种方式。因为在Java中我们访问数据库,有多种选择方案最原始的就是使用 JDBC
或是通过Spring
提供的JdbcTemplate
访问数据库也可以使用Hibernate
,但是为什么要使用Mybatis
呢?我们可以看一下上面使用JDBC
访问数据库的步骤:
- 加载驱动类
- 创建数据库连接
- 创建Statement
- 执行SQL
- 处理SQL执行结果
- 关闭连接
但是核心步骤就只有两个分别是执行SQL和处理SQL结果,从开发来说我们只需要关心这两个步骤,一个简单的查询就需要写一大堆的代码来进行连接,处理什么的特别麻烦,有人会说了那为啥不把上面重复的代码进行封装,对外仅暴露SQL执行和处理结果呢?这样当然是可以的,但是对比Mybatis
来说并不是因为比较繁琐才不去使用JDBC
的,刚刚也看到了使用Mybatis
的话也是比较麻烦的需要进行配置,还要创建XML文件,还要进行绑定。同样如果一个大型的项目使用Mybatis
的话有多少Dao接口就要有多少XML文件,维护起来也很麻烦。
真正的问题
第一个问题就是我们使用JDBC的时候是需要对SQL进行拼接的,很容易就会导致拼接错误,比如多个符号少个逗号的问题第二个问题也是最知名的问题,就是要把SQL写到代码中,这样如果想要改动一下SQL就需要修改代码,同时也会降低代码的可读性,可维护性,从任何角度来说都非常致命。拼接SQL的问题也是有解决的方案使用PreparedStatement
可以解决拼接问题,同时也可以解决SQL注入问题,但是后者是解决不了的。同时现在看一下JDBC在处理查询结果的时候,需要手动从 ResultSet 中取出数据然后在进行处理,上方的例子仅仅使用了两个属性,如果是有很多属性想想就头大
为什么使用Mybatis
接下来就是为什么要使用mybatis
,因为使用mybatis
也是同样的麻烦,Dao层多了也是存在维护性相关的问题。想要维护的话需要付出很大的代价。想要查询数据库同样也是需要很多步骤
首先看一下mybatis
的步骤
- 读取配置文件
- 创建 SqlSessionFactoryBuilder 对象
- 创建SqlSessionFactory
- 通过 SqlSessionFactory 创建 SqlSession
- 为 Dao 接口生成代理类
- 调用接口方法访问数据库
如果每次都需要执行这些步骤的话那它和JDBC没啥区别,而且一点优势都没有。然而并不是,这里参考官方文档SqlSessionFactoryBuilder
和 SqlSessionFactory
以及 SqlSession
等对象 的作用域和生命周期是不一样的。SqlSessionFactoryBuilder
主要用于构建SqlSessionFactory
工厂类,用完就可以抛弃。但是SqlSessionFactory
一旦被创建 就应该在应用运行期间一直存在,不应该丢弃或重建。同时SqlSession 不是线程安全的,不能在多线程中共享,用完即销毁按照自己的需求创建。以上步骤中,读取配置和创建SqlSessionFactoryBuilder
,构建SqlSessionFactory
只需要进行一次第 4 和第 5 步需要进行多次创建。最后一步是必须的。同时也把SQL语句和代码进行了拆分,提高看可读性,同时mybatis
对查询结果进行了映射,无需在手动处理ResultSet
。
总结
对于JDBC来说每一步都是必须的,至于 MyBatis,它是构建在 JDBC 技术之上的, 对访问数据库的操作进行了简化,方便用户使用。JDBC可以看作是一种基础服务,MyBatis
则是在基础服务上面的框架他们的目标不同。使用Mybatis
不仅简化了传统JDBC访问繁琐的问题,还解决了SQL语句与代码的高耦合的问题,同样的也有就是对结果集处理的问题(Mybatis对结果进行了映射)
搭建源码环境
上面介绍了mybatis
是什么、为什么使用、和怎么使用接下来就开始搭建源码环境,同时上面的例子只是简单的使用一下mybatis
下文将对mybatis
进行整合看一下在项目中怎么使用。首先我们打开仓库地址
https://github.com/mybatis/mybatis-3
把项目clone下来,然后在拉取parent
项目parent
中主要就是一些环境依赖。
https://github.com/mybatis/parent.git
创建文件夹mybatissource
,其中包含我们刚刚拉取的项目
然后打开IDEA
点击File>open
然后找到mybatissource
文件夹?,选择mybatissource
点击打开
找到Pom文件
等待依赖加载完毕即可完整项目目录
然后打开Mybatis-3项目在项目src下可自行创建目录
注意测试需要使用junit进行测试
以上就搭建好了源码阅读环境,你也可以自行发挥。同时不建议直接在实际项目中进行debug查询,最好搭建一个源码环境,这样可以一遍debug一遍写笔记。便于后期复习
参考
- 一本小小的mybatis源码分析书
- Mybatis3 源码深度解析
- https://mybatis.org/mybatis-3/zh/index.html
欢迎在评论区留下你的观点,一起讨论提高。