选择响应式网站建设发外链平台
接下来将开辟一个新的专栏Mybatis的原理剖析,里面涉及到了mybatis的整体架构,源码解析等一系列的知识。相信你看完之后则会收获到很多。
MyBatis 是一款开源的持久层框架,它对 JDBC 进行了轻量级封装,帮助开发者更便捷地实现数据库操作。相信JDBC大家都是了解过,JDBC 是 Java 与数据库之间的桥梁,提供统一的 API 让 Java 程序能够操作各种关系型数据库(如 MySQL、Oracle、PostgreSQL 等),无需关心底层数据库的具体实现。那么为什么我们不直接使用JDBC而是通过使用MyBatis来与数据库进行交互呢。下面我们从分析JDBC入手一点点带你了解为什么要有MyBatis以及MyBatis的作用。
为什么不用JDBC?
我们看一下下面这段代码看看JDBC是如何与数据库交互执行一条sql语句的
import java.sql.*;public class JdbcExample {public static void main(String[] args) {// 显式加载MySQL驱动类(适用于旧版本JDBC)Class.forName("com.mysql.cj.jdbc.Driver");// 数据库连接信息String url = "jdbc:mysql://localhost:3306/mydatabase";String username = "root";String password = "password";// SQL 查询语句String sql = "SELECT id, name, age FROM users WHERE age > ?";// 尝试资源语句(自动关闭资源)try (Connection conn = DriverManager.getConnection(url, username, password);PreparedStatement pstmt = conn.prepareStatement(sql)) {// 设置查询参数pstmt.setInt(1, 18); // 查询年龄大于18的用户// 执行查询ResultSet rs = pstmt.executeQuery();// 处理查询结果while (rs.next()) {int id = rs.getInt("id");String name = rs.getString("name");int age = rs.getInt("age");System.out.printf("ID: %d, 姓名: %s, 年龄: %d%n", id, name, age);}} catch (SQLException e) {// 处理数据库操作异常e.printStackTrace();}}
}
上述代码则是JDBC与数据库进行交互的源码,观察上述代码我们发现了JDBC的一些缺点。
// 显式加载MySQL驱动类(适用于旧版本JDBC)Class.forName("com.mysql.cj.jdbc.Driver");// 数据库连接信息String url = "jdbc:mysql://localhost:3306/mydatabase";String username = "root";String password = "password";
这些有关数据库连接的配置文件采用的硬编码的方式实现的,也就是如果更换数据库类型或者数据库连接每次都要修改代码来实现,不仅如此执行sql语句的时候也是通过硬编码来实现的,这样就造成高耦合的效果。
Connection conn = DriverManager.getConnection(url, username, password)
同时呢我们发现每次执行sql数据的时候,都会创建一个数据库连接,这个数据库连接每次创建的时候都要经过tcp三次握手,不仅如此数据连接是一个很珍贵的资源每个项目中的数据连接数量是有限的,如果采用JDBC的方式大量查询sql的时候不仅需要大量的数据库连接同时三次握手也造成性能的损耗
// 处理查询结果while (rs.next()) {int id = rs.getInt("id");String name = rs.getString("name");int age = rs.getInt("age");System.out.printf("ID: %d, 姓名: %s, 年龄: %d%n", id, name, age);}
同时呢每次查询到的数据都要进行手动封装处理的结果,这样做会很繁琐并且如果返回的结果不同那么封装的类型也会不同
因此采用JDBC的方式会造成以下三种问题:
1. 数据库配置文件以及查询的sql语句都需要硬编码来实现
2. 每次执行sql语句的时候都需要创建Connection连接
3. 查询到的数据的结果都需要进行封装
所以mybatis的出现解决了上述的问题。下面我们讲一讲mybatis是如何去做的
mybatis如何做的?
观察上述图我们发现对于JDBC来说几乎所有的操作都是使用者自己去执行的,下面的持久层框架则将一些操作自行封装,使用者仅仅只需要提供配置信息以及sql语句,剩下的一切都交给框架自己去实现这些操作,使得使用者更加专注于sql语句的书写而不需要去管其他的事情。
那么mybatis到底是如何做的呢?
针对上述三个问题mybatis的解决方案:1.采用配置文件的方式进行解耦,2.采用连接池的方式对连接进行管理,3.采用反射的方式对得到的数据进行映射处理
mybatis的架构图:
首先使用端则是提供两个配置文件,sqlMapConfig.xml和mapper.xml的配置文件
sqlMapConfig则是用来存放数据库连接的配置信息的
mapper则是用来存放执行的sql信息的
将这两个配置信息进分离开来原因就是数据库连接信息不经常修改而sql配置信息则总是需要修改。
使用端提供了这些信息那么mybatis是如何处理的呢
首先mybatis第一部需要做的就是将这些配置文件加载成字节流读取放入到内存中去
随后创建两个对象Configuration和MappedStatement分别用来存储配置类sqlMapConfig和mapper的数据的
其次则是解析配置文件通过SqlSessionFactoryBuilder的build方法来解析读取到的配置文件返回一个SqlSessionFactory类这个工厂类,这个工厂类可以通过opSession方法得到sqlSession,这个sqlSession则是真正执行sql 的类,内部含有多个方法对应sql的查询更改删除等操作语句。同时这个过程实际上是使用了工厂模式来实现的,来讲创建对象的复杂过程进行隐藏使得用户无需关心底层是如何创建的,降低耦合度。
那么在sqlSession进行调用方法的过程并不是直接在内部使用JDBC进行调用的,mybatis对JDBC做出了封装处理,封装成了Executor接口和对应的实现类,sqlSession在执行方法的时候通过更加底层的Executor来实现与数据库的交互,Executor在调用方法的时候则需要提供对应的配置信息作为参数,而这些配置信息则已经集成到sqlSession中可以直接使用,并且对于sql中执行的可变参数也是通过方法参数传递下去的。
至此mybatis的整体执行sql的大体框架我们已经介绍完毕,在后续的章节将会对这些执行过程进行更加详细的讲述。