第01篇:Mybatis学习之环境搭建

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
云数据库 RDS PostgreSQL,集群系列 2核4GB
简介: 最早使用Mybatis是在2016年,那时候学习只会用,根本不知道什么原理,不懂的原理的地方只能死记。搭建一个小的demo放到github,工作需要的时候就直接复制黏贴,虽然也能满足工作需要但是总感觉到不带劲。在找到工作后大概2017年时候就对Mybatis的源码进行了阅读,其实相对于Dubbo,Spring,之类的源码Mybatis的源码还是非常简单的,现在也经常推荐给刚开始学习看源码的同学。早在2019年小编就开始写Mybatis的博客了,那时候博客主要还是自己学习为主,现在回头看看,感觉有些粗糙。这里准备回炉重造一波。将原博客进行优化。对Mybaits的核心功能,核心处理类重新重构下博

一、环境搭建

1.1 数据库脚本

SET NAMES utf8;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
--  Table structure for `T_USER`
-- ----------------------------
DROP TABLE IF EXISTS `T_USER`;
CREATE TABLE `T_USER` (
  `uid` int(11) NOT NULL AUTO_INCREMENT COMMENT '用户id',
  `name` char(32) DEFAULT NULL,
  `token_id` char(64) NOT NULL,
  PRIMARY KEY (`uid`,`token_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

SET FOREIGN_KEY_CHECKS = 1;

1.2 POM依赖

<plugin>
    <groupId>org.mybatis.generator</groupId>
    <artifactId>mybatis-generator-maven-plugin</artifactId>
    <version>1.3.2</version>
    <configuration>
        <configurationFile>${basedir}/src/main/resources/generator/generatorConfig.xml</configurationFile>
        <overwrite>true</overwrite>
        <verbose>true</verbose>
    </configuration>
</plugin>

1.3 执行脚本生成代码

mysql数据库记得要安装好,如果clone代码下来学习,记得要改成自己的数据库。
当上面的步骤都完成后,并输入自己的mysql地址和用户信息后。就可以执行下面脚本了。

mvn mybatis-generator:generate

执行后就会生成我们本节要说的所有内容代码了。

➜ tree
.
├── LICENSE
├── README.md
├── pom.xml
└── src
    ├── main
    │   ├── java
    │   │   └── orm
    │   │       └── example
    │   │           └── dal
    │   │               ├── mapper
    │   │               │   └── TUserMapper.java
    │   │               └── model
    │   │                   └── TUser.java
    │   └── resources
    │       ├── generator
    │       │   └── generatorConfig.xml
    │       └── mapper
    │           └── TUserMapper.xml
    └── test
        └── java

13 directories, 7 files

二、原生jdbc知识复习

2.1 JDBC是什么?

JDBC代表Java数据库连接(Java Database Connectivity),它是用于Java编程语言和数据库之间的数据库无关连接的标准Java API,换句话说:JDBC是用于在Java语言编程中与数据库连接的API。

  1. 连接到数据库
  2. 创建SQL或MySQL语句
  3. 在数据库中执行SQL或MySQL查询
  4. 查看和修改结果记录

2.1.1 代码示例

    @Test
    public void jdbc() throws Exception {
        String dbUrl = "jdbc:mysql://127.0.0.1:3306/test";
        String user = "root";
        String pass = "123456";
        Connection connection = DriverManager.getConnection(dbUrl, user, pass);
        Statement statement = connection.createStatement();
        ResultSet resultSet = statement.executeQuery("select * from T_User");
        while (resultSet.next()) {
            String name = resultSet.getString("name");
            System.out.println(name);
        }
        statement.close();
        resultSet.close();
        connection.close();
    }

2.2 jdbc知识点

2.2.1 jdbc驱动

通过前面的例子,我们看到我们都是调用 java.sql的包下面的类创建的与数据库交互的工具。那么我们试想一下。
java怎么知道我们用的数据库是什么呢? 如果不知道他怎么知道如何进行交互呢?

其实就是 java.sql定义了一系列的接口定义, 由具体的第三方数据库来实现这些定义。从而进行底层的交互。
这里因为我们使用的是mysql数据库,所以 Connection的具体实现就是mysql的数据驱动类 ConnectionImpl。

DriverManager 怎么知道我们要用mysql的实现呢? 这里面用到的数据就是java原生的spi能力。

 private static void loadInitialDrivers() {
    ServiceLoader<Driver> loadedDrivers = ServiceLoader.load(Driver.class);
    Iterator<Driver> driversIterator = loadedDrivers.iterator();
 }

当获得了与数据库的连接后,就可以与数据库进行交互了。 JDBC Statement,CallableStatement和PreparedStatement接口定义了可用于发送SQL或PL/SQL命令,并从数据库接收数据的方法和属性。
它们还定义了有助于在Java和SQL数据类型的数据类型差异转换的方法。

接口 说明 特点
Statement 用于对数据库进行通用访问,在运行时使用静态SQL语句时很有用。 Statement接口不能接受参数。 Statement每次的执行都需要编译SQL
PreparedStatement 当计划要多次使用SQL语句时使用。PreparedStatement接口在运行时接受输入参数。 PreparedStatement会预编译,会被缓冲,在缓存区中可以发现预编译的命令,虽然会被再次解析,但不会被再次编译,能够有效提高系统性能
CallableStatement 当想要访问数据库存储过程时使用。CallableStatement接口也可以接受运行时输入参数。 CallableStatement支持存储过程

2.2.2 Statement

Statement对象后,可以使用它来执行一个SQL语句,它有三个执行方法可以执行

  • boolean execute (String SQL) : 如果可以检索到ResultSet对象,则返回一个布尔值true; 否则返回false。使用此方法执行SQLDDL语句或需要使用真正的动态SQL,可使用于执行创建数据库,创建表的SQL语句等等。
  • int executeUpdate (String SQL): 返回受SQL语句执行影响的行数。使用此方法执行预期会影响多行的SQL语句,例如:INSERT,UPDATE或DELETE语句。
  • ResultSet executeQuery(String SQL):返回一个ResultSet对象。 当您希望获得结果集时,请使用此方法,就像使用SELECT语句一样。
    @Test
    public void statement() throws Exception {
        String dbUrl = "jdbc:mysql://127.0.0.1:3306/test";
        String user = "root";
        String pass = "123456";
        Connection connection = DriverManager.getConnection(dbUrl, user, pass);
        connection.setAutoCommit(false);
        Statement statement = connection.createStatement();
        // true
        System.out.println(statement.execute("insert into t_user (name,token_id) values ('孙武空','007')"));
        ResultSet resultSet = statement.executeQuery("select * from t_user");
        while (resultSet.next()) {
            String name = resultSet.getString("name");
            System.out.println(name);
        }
        connection.rollback();
        statement.close();
        connection.close();
    }

2.2.3 PreparedStatement

PreparedStatement接口扩展了Statement接口,它添加了比Statement对象更好一些优点的功能。
此语句可以动态地提供/接受参数。

    @Test
    public void prepareStatement() throws Exception {
        String dbUrl = "jdbc:mysql://127.0.0.1:3306/test";
        String user = "root";
        String pass = "123456";
        Connection connection = DriverManager.getConnection(dbUrl, user, pass);
        connection.setAutoCommit(false);
        PreparedStatement preparedStatement = connection.prepareStatement("insert into t_user (name,token_id) values (?,?)");
        preparedStatement.setString(1, "唐三藏");
        preparedStatement.setString(2, "tok");
        preparedStatement.execute();

        ResultSet resultSet = preparedStatement.executeQuery("select * from t_user");
        while (resultSet.next()) {
            String name = resultSet.getString("name");
            System.out.println(name);
        }
        connection.rollback();
        preparedStatement.close();
        connection.close();
    }

2.2.4 CallableStatement

类似Connection对象创建Statement和PreparedStatement对象一样,它还可以使用同样的方式创建CallableStatement对象,该对象将用于执行对数据库存储过程的调用。

    @Test
    public void callableStatement() throws Exception {
        String dbUrl = "jdbc:mysql://127.0.0.1:3306/test";
        String user = "root";
        String pass = "123456";
        Connection connection = DriverManager.getConnection(dbUrl, user, pass);
        // 1. 创建一个存储过程
        String call =
                "CREATE PROCEDURE delete_matches(IN del_name varchar(64))\n" +
                        "begin\n" +
                        "    delete from t_user where name = del_name;\n" +
                        "end;";
        Statement statement = connection.createStatement();
        statement.execute("DROP PROCEDURE IF EXISTS delete_matches;");
        statement.execute(call);

        // 执行存储过程
        CallableStatement callableStatement = connection.prepareCall("call delete_matches(?)");
        callableStatement.setString(1, "孙武空");
        callableStatement.execute();

        // 查询结果检查存储过程是否成功
        ResultSet resultSet = statement.executeQuery("select * from t_user");
        while (resultSet.next()) {
            String name = resultSet.getString("name");
            System.out.println(name);
        }
        statement.close();
        callableStatement.close();
        connection.close();
    }

:::tip
jdbc主要提供跟数据库的交互,其主要的类就是上面演示的。通过上面的复习。我们要清楚下面几个类的作用。
后面我们在学习mybatis时候,我们看mybatis是如何对下面类的封装,从而实现orm映射的。
:::

关键类 说明
Connection 数据库连接
Statement 静态sql执行
PreparedStatement 预处理sql
CallableStatement 存储过程执行
ResultSet 返回结果集

三、抛转引玉

前面我们首先搭建了mybaits的开发环境,然后又对jdbc的知识进行了复习。下面我们就开始学习mybait的源码,看mybatis是如何对
jdbc一步一步进行封装从而实现了orm的映射吧。
首先我们先看下下面演示代码。

    @Test
    public void mapper() {
        // 读取配置信息(为什么路径前不用加/,因为是相对路径。maven编译后的资源文件和class文件都是在一个包下,所以不用加/就是当前包目录)
        InputStream mapperInputStream = Thread.currentThread().getContextClassLoader().getResourceAsStream("mybatisConfig.xml");
        // 生成SqlSession工厂,SqlSession从名字上看就是,跟数据库交互的会话信息,负责将sql提交到数据库进行执行
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(mapperInputStream, "development");
        // 获取Mybatis配置信息
        Configuration configuration = sqlSessionFactory.getConfiguration();
        // 参数: autoCommit,从名字上看就是是否自动提交事务
        SqlSession sqlSession = sqlSessionFactory.openSession(false);
        // 获取Mapper
        TUserMapper mapper = configuration.getMapperRegistry().getMapper(TUserMapper.class, sqlSession);
        TUser tUser = new TUser();
        tUser.setName("testUser1");
        tUser.setTokenId("testTokenId1");
        mapper.insert(tUser);
        // 获取插入的数据
        System.out.println(mapper.selectAll());
        // 数据插入后,执行查询,然后回滚数据
        sqlSession.rollback();
    }

jdbc的原生操作基本已经看不到了。我们已经使用Mybatis实现了与数据库的交互。可以看到并没有看到sql信息。
因为sql信息都维护在TUserMapper.xml里面,Mybatis帮我们把TUserMapper.xml和TUserMapper建立了关系。
最终将原本要通过jdbc实现的操作通过代理的方式,并最终通过TUserMapper这个接口进行交互了。

请问到这里勾起你的好奇心了没有呢? 想不想知道为什么能这样吗? 想不想知道mybaits究竟做了什么,以及是怎么做的呢?
本系列文章会带你一探究竟。在开始之前我们先指定一下学习目标吧。

3.1 学习目标制定

  • 配置文件是如何解析成 Configuration ?
  • sql 和数据库是如何交互的 SqlSession ?
  • mapper.xmlMapper 是如何绑定的MapperRegistry ?
  • Mybatis 是如何做动态代理的 ?
  • Mybatis中如何利用插件实现扩展的?
  • Jdbc的Statement在Mybatis是如何封装的?
  • 以及Mybatis中很多好用的工具类.

3.2 学习后我们能得到什么

  • 从配置文件解析中我们能学会,如果解析占位符。并将占位符填充真实数据。
  • 通过对 SqlSession 的学习,我们会了解到Mybatis的缓存设计,批处理任务,事务等操作。
  • 通过对 MapperRegistry 的学习, 我们会了解到如何实现 orm(对象关系映射) 框架。
  • 我们会收货很多设计的思路,而思路决定出路。
相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
2月前
|
Java 关系型数据库 MySQL
springboot学习五:springboot整合Mybatis 连接 mysql数据库
这篇文章是关于如何使用Spring Boot整合MyBatis来连接MySQL数据库,并进行基本的增删改查操作的教程。
212 0
springboot学习五:springboot整合Mybatis 连接 mysql数据库
|
3月前
|
Java 关系型数据库 数据库连接
mybatis-plus学习
MyBatis-Plus ,MyBatis 最佳搭档,只做增强不做改变,为简化开发、提高效率而生。
51 5
|
4月前
|
安全 Java 数据库连接
后端框架的学习----mybatis框架(3、配置解析)
这篇文章详细介绍了MyBatis框架的核心配置文件解析,包括环境配置、属性配置、类型别名设置、映射器注册以及SqlSessionFactory和SqlSession的生命周期和作用域管理。
后端框架的学习----mybatis框架(3、配置解析)
|
4月前
|
Java 数据库连接 mybatis
后端框架的学习----mybatis框架(9、多对一处理和一对多处理)
这篇文章介绍了在MyBatis框架中如何处理多对一和一对多的关联查询,通过定义`<resultMap>`和使用`<association>`与`<collection>`元素来实现对象间的关联映射。
|
4月前
|
Java 数据库连接 测试技术
后端框架的学习----mybatis框架(8、lombok)
这篇文章介绍了如何在MyBatis框架中使用lombok库来简化Java实体类的编写,包括在IDEA中安装Lombok插件、在项目中导入lombok依赖以及在实体类上使用Lombok提供的注解。
|
4月前
|
Java 数据库连接 数据库
后端框架的学习----mybatis框架(6、日志)
这篇文章介绍了如何在MyBatis框架中使用日志功能,包括配置MyBatis的日志实现、使用log4j作为日志工具,以及如何通过配置文件控制日志级别和输出格式。
|
4月前
|
SQL Java 数据库连接
后端框架的学习----mybatis框架(5、分页)
这篇文章介绍了如何在MyBatis框架中实现分页功能,包括使用SQL的`limit`语句进行分页和利用MyBatis的`RowBounds`对象进行分页的方法。
|
4月前
|
SQL Java 数据库连接
后端框架的学习----mybatis框架(7、使用注解开发)
这篇文章讲述了如何使用MyBatis框架的注解方式进行开发,包括在接口上使用注解定义SQL语句,并通过动态代理实现对数据库的增删改查操作,同时强调了接口需要在核心配置文件中注册绑定。
|
7月前
|
SQL Java 数据库连接
【Mybatis】深入学习MyBatis:概述、主要特性以及配置与映射
【Mybatis】深入学习MyBatis:概述、主要特性以及配置与映射
【Mybatis】深入学习MyBatis:概述、主要特性以及配置与映射
|
6月前
|
Java 数据库连接 Maven
Mybatis学习
Mybatis学习
31 0
下一篇
DataWorks