看完这篇文章,小白也能手写mybatis框架

这篇博客详细介绍了如何从零开始构建一个简单的Mybatis框架。首先分析了原始JDBC存在的问题,如硬编码、资源浪费等,然后提出了设计思路,包括使用端和框架端的实现。接着通过解析XML配置文件,创建SqlSessionFactory和SqlSession,实现参数注入和结果集反射封装。博主提供了完整的实现过程和测试,帮助读者理解Mybatis的工作原理。
摘要由CSDN通过智能技术生成

目录

前言

原始 JDBC 存在的问题

我们知道最原始的数据库操作。分为以下几步

设计思路

使用端

框架端

那在 SqlSession 中 进行了哪些操作呢?

使用端实现

框架端实现

XmlConfigBuilder

创建 SqlSessionFactory

SqlSession 具体实现

{username} 这样的 sql 我们该怎么解析呢?

将参数注入到 preparedStatement 中

通过反射将结果集封装成对象

创建 SqlSessionFactoryBuilder

测试

优化

接下来我们在写一个测试方法

番外


前言

mybaits 在 ORM 框架中,可算是半壁江山了,由于它是轻量级,半自动加载,灵活性和易拓展性。深受广大公司的喜爱,所以我们程序开发也离不开 mybatis 。但是我们有对 mabtis 源码进行研究吗?或者想看但是不知道怎么看的苦恼吗?  归根结底,我们还是需要知道为什么会有 mybatis ,mybatis 解决了什么问题? 想要知道 mybatis 解决了什么问题,就要知道传统的 JDBC 操作存在哪些痛点才促使 mybatis 的诞生。 我们带着这些疑问,再来一步步学习吧。

上面的一份详细的mybatis的学习思维导图已整理好,还有一些mybatis的技术资料文档,需要领取可以 点我领取

原始 JDBC 存在的问题

所以我们先来来看下原始 JDBC 的操作

我们知道最原始的数据库操作。分为以下几步

1、获取 connection 连接

2、获取 preparedStatement

3、参数替代占位符

4、获取执行结果 resultSet

5、解析封装 resultSet 到对象中返回。

如下是原始 JDBC 的查询代码,存在哪些问题?

public static void main(String[] args) {
        String dirver="com.mysql.jdbc.Driver";
        String url="jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8";
        String userName="root";
        String password="123456";

        Connection connection=null;
        List<User> userList=new ArrayList<>();
        try {
            Class.forName(dirver);
            connection= DriverManager.getConnection(url,userName,password);

            String sql="select * from user where username=?";
            PreparedStatement preparedStatement=connection.prepareStatement(sql);
            preparedStatement.setString(1,"张三");
            System.out.println(sql);
            ResultSet resultSet=preparedStatement.executeQuery();

            User user=null;
            while(resultSet.next()){
                user=new User();
                user.setId(resultSet.getInt("id"));
                user.setUsername(resultSet.getString("username"));
                user.setPassword(resultSet.getString("password"));
                userList.add(user);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            try {
                connection.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }

        if (!userList.isEmpty()) {
            for (User user : userList) {
                System.out.println(user.toString());
            }
        }

    }

小伙伴们发现了上面有哪些不友好的地方?

我这里总结了以下几点:

1、数据库的连接信息存在硬编码,即是写死在代码中的。 2、每次操作都会建立和释放 connection 连接,操作资源的不必要的浪费。 3、sql 和参数存在硬编码。 4、将返回结果集封装成实体类麻烦,要创建不同的实体类,并通过 set 方法一个个的注入。

存在上面的问题,所以 mybatis 就对上述问题进行了改进。 对于硬编码,我们很容易就想到配置文件来解决。mybatis 也是这么解决的。 对于资源浪费,我们想到使用连接池,mybatis 也是这个解决的。 对于封装结果集麻烦,我们想到是用 JDK 的反射机制,好巧,mybatis 也是这么解决的。

设计思路

既然如此,我们就来写一个自定义持久层框架,来解决上述问题,当然是参照 mybatis 的设计思路,这样我们在写完之后,再来看 mybatis 的源码就恍然大悟,这个地方这样配置原来是因为这样啊。

我们分为使用端和框架端两部分。

使用端

我们在使用 mybatis 的时候是不是需要使用 SqlMapConfig.xml 配置文件,用来存放数据库的连接信息,以及 mapper.xml 的指向信息。mapper.xml 配置文件用来存放 sql 信息。

所以我们在使用端来创建两个文件 SqlMapConfig.xml 和 mapper.xml。

框架端

框架端要做哪些事情呢?

如下:

1、获取配置文件。也就是获取到使用端的 SqlMapConfig.xml 以及 mapper.xml 的文件

2、解析配置文件。对获取到的文件进行解析,获取到连接信息,sql,参数,返回类型等等。这些信息都会保存在 configuration 这个对象中。

3、创建 SqlSessionFactory,目的是创建 SqlSession 的一个实例。

4、创建 SqlSession ,用来完成上面原始 JDBC 的那些操作。

那在 SqlSession 中 进行了哪些操作呢?

1、获取数据库连接

2、获取 sql ,并对 sql 进行解析

3、通过内省,将参数注入到 preparedStatement 中

4、执行 sql

5、通过反射将结果集封装成对象

使用端实现

好了,上面说了一下,大概的设计思路,主要也是仿照 mybatis 主要的类实现的,保证类名一致,方便我们后面阅读源码。我们先来配置好使用端吧,我们创建一个 maven 项目。

在项目中,我们创建一个 User 实体类

public class User {
    private Integer id;
    private String username;
    private String password;
    private String birthday;
    //getter()和 setter()方法
}

创建 SqlMapConfig.xml 和 Mapper.xml SqlMapConfig.xml

<?xml version="1.0" encoding="UTF-8" ?>
<configuration>
    <property name="driverClass" value="com.mysql.jdbc.Driver"></property>
    <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/mybatis?serverTimezone=UTC&amp;characterEncoding=utf8&amp;useUnicode=true&amp;useSSL=false"></property>
    <property name="userName" value="root"></property>
    <property name="password" value="123456"></property>

    <mapper resource="UserMapper.xml">
    </mapper>
</configuration>

可以看到我们 xml 中就配置了数据库的连接信息,以及 mapper 一个索引。mybatis 中的 SqlMapConfig.xml 中还包含其他的标签,只是丰富了功能而已,所以我们只用最主要的。

mapper.xml 是每个类的 sql 都会生成一个对应的 mapper.xml 。我们这里就用 User 类来说吧,所以我们就创建一个 UserMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<mapper namespace="cn.quellanan.dao.UserDao">
    <select id="selectAll" resultType="cn.quellanan.pojo.User">
        select * from user
    </select>
    <select id="selectByName" resultType="cn.quellanan.pojo.User" paramType="cn.quellanan.pojo.User">
        select * from user where username=#{username}
    </select>
</mapper>

可以看到有点 mybatis 里面文件的味道,有 namespace 表示命名空间,id 唯一标识,resultType 返回结果集的类型,paramType 参数的类型。 我们使用端先创建到这,主要是两个配置文件,我们接下来看看框架端是怎么实现的。

加油哈哈。 

框架端实现

框架端,我们按照上面的设计思路一步一步来。

获取配置

怎么样获取配置文件呢?我们可以使用 JDK 自带自带的类 Resources 加载器来获取文件。我们创建一个自定义 Resource 类来封装一下:

import java.io.InputStream;
public class Resources {
    public  static InputStream getResources(String path){
        //使用系统自带的类 Resources 加载器来获取文件。
        return Resources.class.getClassLoader().getResourceAsStream(path);
    }
}

这样通过传入路径,就可以获取到对应的文件流啦。

解析配置文件

上面获取到了 SqlMapConfig.xml 配置文件,我们现在来解析它。 不过在此之前,我们需要做一点准备工

  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值