在之前的文章中,我为大家介绍了 Mybatis 的详细用法,算是基础教程。

  详细链接:Mybatis 基础教程

  言归正传,只懂基础可不行,接下来将给大家带来高阶的源码解析教程,从浅入深,通过源码解析,图例结合,抽丝剥茧,让大家看的不吃力,并且能够深刻理解 Mybatis 这个框架的底层实现原理,让大家学到的不仅仅是这个框架用法,而是通过这个框架理解其设计思想。

  

1、JDBC

  我相信所有开发者第一次与数据库打交道时,就是通过 JDBC 来实现的,第一次通过程序获取到数据库中的数据时,那种高兴,那种吃惊,反正我依稀历历在目。            

  什么是 JDBC:JDBC 是Java与数据库交互的API,用来规范客户端程序如何来访问数据库的应用程序接口。

  通常分为两组API:

  ①、面向Java应用程序开发人员的API,是一个标准的API,且不同数据库具有不同的实现。

  ②、面向数据库驱动开发人员,是前者的底层支持。

  因为大家都是Java开发人员,这里我们就介绍第一组API。

  JDBC API主要位于JDK中的java.sql包中(之后扩展的内容位于javax.sql包中)

  下面介绍几个关键的接口,注意这都是JDK内部提供的一些接口,具体实现得看具体的数据库驱动,比如MySQL,我们通常会在maven或gradle配置mysql-connectior-java ,下面接口的具体实现就在其中。

  ①、Driver:驱动程序,会将自身加载到DriverManager中去.

  ②、DriverManager:负责加载各种不同驱动程序(Driver),并根据不同的请求,向调用者返回相应的数据库连接(Connection)。

  ③、Connection:数据库连接,负责与进行数据库间通讯,SQL执行以及事务处理都是在某个特定Connection环境中进行的。可以产生用以执行SQL的Statement。

  ④、Statement:用来执行SQL查询和更新(针对静态SQL语句和单次执行)。

  ⑤、PreparedStatement:用来执行包含动态参数的SQL查询和更新(预编译,在服务器端编译,允许重复执行以提高效率)。

  ⑥、CallableStatement:用来调用数据库中的存储过程。

  ⑦、ResultSet:用来存储数据库查询操作返回的结果。

  ⑧、SQLException:表示在数据库连接的建立、SQL语句的执行、关闭等过程中发生了异常。

2、完整的交互过程

  下面,我们通过JDBC来完成一次数据库查询操作,步骤如下:

  ①、加载数据库驱动

  ②、获取数据库连接(通过数据库URL,用户名,密码)

  ③、定义SQL语句

  ④、通过数据库连接,创建 Statement 对象或者 PreparedStatement 对象

  ⑤、通过 Statement 对象执行 SQL 语句,得到结果集 ResultSet 对象

  ⑥、读取 ResultSet 对象,转换成我们要的 JavaBean

  ⑦、关闭数据库连接、Statement、ResultSet等对象,释放相关资源

代码实现如下:

  1. package com.itcoke.bean;
  2.  
  3. public class Person {
  4.  
  5. private Long pid;
  6.  
  7. private String pname;
  8.  
  9. private Integer page;
  10.  
  11. public Long getPid() {
  12. return pid;
  13. }
  14.  
  15. public void setPid(Long pid) {
  16. this.pid = pid;
  17. }
  18.  
  19. public String getPname() {
  20. return pname;
  21. }
  22.  
  23. public void setPname(String pname) {
  24. this.pname = pname;
  25. }
  26.  
  27. public Integer getPage() {
  28. return page;
  29. }
  30.  
  31. public void setPage(Integer page) {
  32. this.page = page;
  33. }
  34.  
  35. @Override
  36. public String toString() {
  37. return "Person{" +
  38. "pid=" + pid +
  39. ", pname='" + pname + '\'' +
  40. ", page=" + page +
  41. '}';
  42. }
  43. }
  1. package com.itcoke.jdbc;
  2.  
  3. import com.itcoke.bean.Person;
  4.  
  5. import java.sql.*;
  6. import java.util.ArrayList;
  7. import java.util.List;
  8.  
  9. public class JDBCUtils {
  10. //MySQL数据库驱动,注意多了一个cj,com.mysql.jdbc.Driver和mysql-connector-java 5一起用
  11. public static String driverClass = "com.mysql.cj.jdbc.Driver";
  12. //MySQL用户名
  13. public static String userName = "root";
  14. //MySQL密码
  15. public static String passWord = "root1234";
  16. //MySQL URL
  17. public static String url = "jdbc:mysql://localhost:3306/mybatis-study";
  18. //定义数据库连接
  19. public static Connection conn = null;
  20. //定义声明数据库语句,使用 预编译声明 PreparedStatement提高数据库执行性能
  21. public static PreparedStatement ps = null;
  22. //定义返回结果集
  23. public static ResultSet rs = null;
  24.  
  25. public static List<Person> selectPersonByName(String pname){
  26. List<Person> personList = new ArrayList<>();
  27.  
  28. try {
  29. // 1、加载数据库驱动
  30. Class.forName(driverClass);
  31. // 2、获取数据库连接
  32. conn = DriverManager.getConnection(url,userName,passWord);
  33. // 3、定义 sql 语句,?表示占位符
  34. String sql = "select * from person where pname=?";
  35. // 4、获取预编译处理的statement
  36. ps = conn.prepareStatement(sql);
  37. //设置sql语句中的参数,第一个为sql语句中的参数的?(从1开始),第二个为设置的参数值
  38. ps.setString(1, "itcoke");
  39. // 5、向数据库发出 sql 语句查询,并返回结果集
  40. rs = ps.executeQuery();
  41. while(rs.next()){
  42. // 6、读取ResultSet,转换成我们要的对象
  43. Person person = new Person();
  44. person.setPid(rs.getLong("pid"));
  45. person.setPname(rs.getString("pname"));
  46. personList.add(person);
  47. }
  48. } catch (Exception e) {
  49. e.printStackTrace();
  50. }finally{
  51. // 7、关闭数据库连接
  52. if(rs!=null){
  53. try {
  54. rs.close();
  55. } catch (SQLException e) {
  56. e.printStackTrace();
  57. }
  58. }
  59. if(ps!=null){
  60. try {
  61. ps.close();
  62. } catch (SQLException e) {
  63. e.printStackTrace();
  64. }
  65. }
  66. if(conn!=null){
  67. try {
  68. conn.close();
  69. } catch (SQLException e) {
  70. e.printStackTrace();
  71. }
  72. }
  73. }
  74. return personList;
  75. }
  76.  
  77. public static void main(String[] args){
  78. List<Person> personList = JDBCUtils.selectPersonByName("itcoke");
  79. System.out.println(personList);
  80. }
  81. }

  PS:数据库名称为 mybatis-study,表为 person

  

3、缺点分析

  ①、问题一:每执行一次增删改查,就要建立连接,关闭连接,频繁的获取连接和关闭连接,会造成数据库资源浪费,影响数据库性能。

  设想解决:使用数据库连接池管理数据库连接

  ②、问题二:将 sql 语句硬编码到程序中,如果sql语句修改了,那么需要重新编译 Java 代码,不利于系统维护

  设想解决:将 sql 语句可配置化,比如设置到 xml 文件中,这样即使 sql 语句变化了,我们也不需要对 Java 代码进行修改

  ③、问题三:在 PreparedStatement 中设置参数,对占位符设置值都是硬编码在Java代码中,不利于系统维护

  设想解决:将 sql 语句以及占位符和参数都配置到 xml 文件中

  ④、问题四:从 resultset 中遍历结果集时,对表的字段存在硬编码,不利于系统维护

  设想解决:将查询的结果集自动映射为 Java 对象

  ⑤、问题五:重复性代码特别多,包括建立建立,加载驱动等

  设想解决:抽取封装公共代码

  ⑥、问题六:没有缓存,如果存在数据量大,且频繁查询的情况,这种方式性能特别低

  设想解决:集成缓存框架去操作数据库

  ⑦、问题七:sql 的移植性不好,如果换个数据库,那么sql 语句可能要重写

  设想解决:在 JDBC 和 数据库之间插入第三方框架,用第三方去生成 sql 语句,屏蔽数据库的差异

4、ORM框架

  为了解决上面这些缺点,ORM(Object Relational Mapping,对象-关系映射)框架应运而生。

  ORM 模型就是数据库的表和Java对象的映射关系模型,它主要解决数据库数据和Java对象的相互映射,通过映射关系,我们可以简单而迅速的把数据库数据转换成Java对象,从而让开发人员无需对数据库相关知识深入了解,便可以操作数据库数据。

  当前市面上比较主流的ORM框架包括 Hibernate、Mybatis、Spring JDBC 等等,各有优缺点,这里可乐不做详细介绍,本系列文章主要是介绍当前使用最广泛的 ORM框架——Mybatis。

  其更轻量、更可控的特性,比较适合当前主流业务,特别是大数据量、高并发的场景。

5、小结

  本文我们介绍了JDBC直接操作数据库的一些问题,引申出解决此类问题的ORM框架,其中 Mybatis 是其中的佼佼者,

  那么为什么 Mybatis 能够解决 JDBC 直接操作数据库的痛点?它又是如何实现的呢?

  不要走开,我们下篇文章更精彩!

Mybatis源码解析1—— JDBC的更多相关文章

  1. 【Mybatis源码解析】- JDBC连接数据库的原理和操作

    JDBC连接数据库的原理和操作 JDBC即Java DataBase Connectivity,java数据库连接:JDBC 提供的API可以让JAVA通过API方式访问关系型数据库,执行SQL语句, ...

  2. mybatis源码-解析配置文件(三)之配置文件Configuration解析

    目录 1. 简介 1.1 系列内容 1.2 适合对象 1.3 本文内容 2. 配置文件 2.1 mysql.properties 2.2 mybatis-config.xml 3. Configura ...

  3. Mybatis源码解析,一步一步从浅入深(一):创建准备工程

    Spring SpringMVC Mybatis(简称ssm)是一个很流行的java web框架,而Mybatis作为ORM 持久层框架,因其灵活简单,深受青睐.而且现在的招聘职位中都要求应试者熟悉M ...

  4. Mybatis源码解析,一步一步从浅入深(三):实例化xml配置解析器(XMLConfigBuilder)

    在上一篇文章:Mybatis源码解析,一步一步从浅入深(二):按步骤解析源码 ,中我们看到 代码:XMLConfigBuilder parser = new XMLConfigBuilder(read ...

  5. Mybatis源码解析,一步一步从浅入深(四):将configuration.xml的解析到Configuration对象实例

    在Mybatis源码解析,一步一步从浅入深(二):按步骤解析源码中我们看到了XMLConfigBuilder(xml配置解析器)的实例化.而且这个实例化过程在文章:Mybatis源码解析,一步一步从浅 ...

  6. Mybatis源码解析,一步一步从浅入深(七):执行查询

    一,前言 我们在文章:Mybatis源码解析,一步一步从浅入深(二):按步骤解析源码的最后一步说到执行查询的关键代码: result = sqlSession.selectOne(command.ge ...

  7. Mybatis源码解析(四) —— SqlSession是如何实现数据库操作的?

    Mybatis源码解析(四) -- SqlSession是如何实现数据库操作的?   如果拿一次数据库请求操作做比喻,那么前面3篇文章就是在做请求准备,真正执行操作的是本篇文章要讲述的内容.正如标题一 ...

  8. Mybatis源码解析(二) —— 加载 Configuration

    Mybatis源码解析(二) -- 加载 Configuration    正如上文所看到的 Configuration 对象保存了所有Mybatis的配置信息,也就是说mybatis-config. ...

  9. Mybatis源码解析3——核心类SqlSessionFactory,看完我悟了

    这是昨晚的武汉,晚上九点钟拍的,疫情又一次来袭,曾经熙熙攘攘的夜市也变得冷冷清清,但比前几周要好很多了.希望大家都能保护好自己,保护好身边的人,生活不可能像你想象的那么好,但也不会像你想象的那么糟. ...

随机推荐

  1. 上海某大公司:你是了解Redis对吧?

    <对线面试官>系列目前已经连载26篇啦!有深度风趣的系列! [对线面试官]Java注解 [对线面试官]Java泛型 [对线面试官] Java NIO [对线面试官]Java反射 & ...

  2. rsync 基本使用

    基本参数 # rsync -P test.tar.gz ./ test.tar.gz 395,706,368 48% 377.34MB/s 0:00:01 Or # rsync -avPh test. ...

  3. 39、wget、curl

    39.1.wget介绍: wget命令用来从指定的URL下载文件.wget非常稳定,它在带宽很窄的情况下和不稳定网络中有很强的适应性,如果是由于网络的原因下载失败, wget会不断的尝试,直到整个文件 ...

  4. 企业该选择什么样的CRM系统

    不论您是需要CRM系统来优化业务流程,还是准备更换一款新的CRM系统,在这之前都应该先明确企业的需求,并了解CRM的哪些功能能够对企业有所帮助.例如,企业的管理者想了解每个销售人员的业绩情况,那么就应 ...

  5. sqlite用法总结

    p.p1 { margin: 0; font: 16px "Helvetica Neue"; color: rgba(0, 0, 255, 1) } p.p2 { margin: ...

  6. 严重:Exception sending context initialized event to listener instance of class [myJava.MyServletContextListener] java.lang.NullPointerException

    以上错误是我在自定义Servlet监听器时遇到的,首先大致介绍一下我要实现的功能(本人刚开始学,如有错误,请多多指正): 为了统计网站访问量,防止服务器重启后,原访问次数被清零,因此自定义监听器类,实 ...

  7. SqlServer常用语句整理

    先记录下来 以后整理 1.常用语句 1.1update连表更新 update a set a.YCaseNo = a.WordName + '['+ convert(varchar,a.CaseYea ...

  8. 续PA协商过程

    续PA协商过程 当sw3的接口恢复之后会发生2中情况. ①sw3的G0/0/2口先发BPDU ②sw3的G0/0/3口先发BPDU sw3先发送BPDU sw3和sw1的交互过程: sw3的2口恢复后 ...

  9. Windows内核开发-2-开始内核开发-2-内核开发入门

    Windows内核开发-2-开始内核开发-2- 第一个驱动程序: 直接采用vs2019中的Empty WDM Driver 模块创建: 初始的项目文件夹中有一个Driver Files里面会有一个.i ...

  10. 「CF585E」 Present for Vitalik the Philatelist

    「CF585E」 Present for Vitalik the Philatelist 传送门 我们可以考虑枚举 \(S'=S\cup\{x\}\),那么显然有 \(\gcd\{S'\}=1\). ...