本系列内容都是阅读芋道源码MyBatis篇后总结记录
1.何为Mybatis
首先我们需要清楚MyBatis是什么?而你又是否能够说出它解决了什么?
当然有人可能会不在意,认为我都用了这么久的MyBatis了,会不知道它是什么?这个时候请给自己一点时间,在脑海中自己来回答这个问题:MyBatis是什么?
有人也会问:我清楚呀,这个MyBatis框架是干嘛的?但是这有什么用么?
注意:这非常有用,你会让你抓住他的本质,会让你在MyBatis的源码世界里点亮一盏明灯。
OK,说了那么多废物,我们可以来回答上面抛出的问题了:何为是MyBatis?
先说说我个人对他的理解:
MyBatis解决了传统JDBC操作数据库的繁琐问题,减少了代码的冗余、可维护性和可阅读性。实现了对于JDBC传统操作数据库返回结果的映射封装。
可能会觉得我说的比较low,所以我也附上MyBatis官网对于自己的定位理解:
MyBatis 是一款优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以使用简单的 XML 或注解来配置和映射原生类型、接口和 Java 的 POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。
如果想要知其所以然,那么我们不得不倒退到那个没有MyBatis等框架的年代,站在他们的历史角度来查看是如何操作的。
2. 传统JDBC操作数据库
这里我们直接使用maven,引入对应依赖包:
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.39</version>
</dependency>
这里我们是以Mysql5.+版本来进行演示的,代码如下:
public class JDBCDemo {
private static final String MYSQL_URL = "jdbc:mysql://localhost:3306/test_demo?useUnicode=true&characterEncoding=UTF-8";
private static final String MYSQL_USER = "root";
private static final String MYSQL_PWD = "111111";
public static void main(String[] args) throws ClassNotFoundException, SQLException {
//加载mysql驱动,mysql8.0版本以上使用com.mysql.cj.jdbc.Driver驱动
Class.forName("com.mysql.jdbc.Driver");
//获取数据库连接<1>
Connection connection = DriverManager.getConnection(MYSQL_URL, MYSQL_USER, MYSQL_PWD );
//sql预编译查询<2>
PreparedStatement preparedStatement = connection
.prepareStatement("select * from websites where name =? ");
preparedStatement.setString(1,"淘宝");
System.out.println(preparedStatement.toString());
//结果输出<3>
ResultSet resultSet = preparedStatement.executeQuery();
while (resultSet.next()){
System.out.printf("id = %d, name= %s,", resultSet.getInt("id"), resultSet.getString("name"));
}
resultSet.close();
preparedStatement.close();
connection.close();
}
}
- 注意:这块代码的数据库基础我们可以参考Mysql菜鸟教程
- <1>: 我们通过url、name、password来连接数据库,得到Connection
- <2>: 构建PreparedStatement进行SQL编译解析
- <3>: 获取SQL执行结果
我们可以看出执行一句简单的SQL,我们要准备大量的、与实际业务无关的代码,会极大的拖慢我们的运行效率
2.1 为何使用PreparedStatement来操作数据库
上面的代码部分我们使用了PreparedStatement进行操作,当然我们也知道除了这个之外我们还有一个Statement,但是为何我们会选择PreparedStatement而抛弃使用Statement呢?
这里我们会直接脱口而出,防止SQL注入。OK,你回答的没有错,但我猜想你可能只是从面试题或等等地方看到了,那在深层次,你知道这是如何防止的么?我们以 select * from websites where name =? 为例来进行说明:
- Statement是使用SQl拼接的方式组装SQL,也就是说Statement只负责把传进来的SQL字符串整体传递给数据库进行编译并运行,那么假设我们传进来的参数是1 or true 来替换?,那么我们会把数据库的所有内容都返回
- 要想了解PreparedStatement预编译过程,我们的先了解JDBC是如何与MySQL服务进行交互的:
- SQL语句仅仅是普通的文本语言,数据库引擎无法识别,所以需要编译再来执行
- Statement执行过程是:提交SQL语言 -> 数据库引擎编译可执行代码 -> 执行SQL代码
- PreparedStatement执行过程: 将不是完整的SQL语言(带有?参数的)提交给数据库编译放回执行代码句柄,之后在句柄中添加相应的参数(注意传入参数都是字符串,不会编译成SQL关键字),之后直接调用execute()方法就行。 - PreparedStatement采用预编译手段,也可以提高重复SQL的执行效率问题,可节约重复编译的时间
3 传统JDBC操作方式的痛点
人是懒惰的,所以在看到这种情况下,影响的数据库封装框架应运而生,那么我们先来总结下他的痛点:
核心痛点:
- 代码冗余,复杂性高,执行简单一条SQL步骤复杂
- 数据库返回结果获取
其他痛点: - 数据库连接
- 无法支持动态SQL
4 MyBatis框架的使用场景
MyBatis是半自动框架,个人认为比较适用于相对较为复杂的业务场景。如需简单操作,比较适合jpa方式或者使用MyBatis Plus。
5.今日总结
我们简单的回顾了过去时代操作数据库的繁杂,以及分析了关于PreparedStatement操作数据库的优点。今日纯粹铺垫,但是我们也可以抛出一个问题:
如果是你当初站在那个历史的拐弯点,你会如何搭建属于你的对应数据库映射框架,带着你的思考,在接下来可以更好的融入MyBatis的源码世界。
网友评论