• MyBatis源码之前言—JDBC编码存在的问题和Mybatis的介绍


    MyBatis源码之前言—JDBC编码存在的问题和Mybatis的介绍

    为了方便操作,我们在sjdwz_test数据库下建立一张表:

    CREATE TABLE `t_student` (
      `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',
      `name` varchar(255) DEFAULT NULL COMMENT '名字',
      `age` int(255) DEFAULT NULL COMMENT '年龄',
      PRIMARY KEY (`id`) USING BTREE
    ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4;
    

    数据如下:

    数据

    实体类如下:

    package com.sjdwz.db;
    
    import lombok.*;
    
    /**
     * @Description 数据库实体
     * @Created by 随机的未知
     */
    @Data
    @ToString
    @NoArgsConstructor
    @AllArgsConstructor
    @Builder
    public class Student {
        private Long id;
        private String name;
        private Integer age;
    }
    
    

    JDBC操作数据库

    我们先来回顾一下JDBC操作数据库的代码:

    package com.sjdwz.jdbc;
    
    import com.sjdwz.db.Student;
    
    import java.sql.*;
    import java.util.ArrayList;
    import java.util.List;
    
    /**
     * @Description JDBC操作数据库代码示例
     * @Date 2023/12/14
     * @Created by 随机的未知 sjdwz.com
     */
    public class JDBCMain {
        public static void main(String[] args) throws SQLException, ClassNotFoundException {
            //数据库连接地址
            String url = "jdbc:mysql://localhost:3306/sjdwz_test";
            String user = "root";//用户名
            String password = "1234567";//密码
            //1.注册数据库驱动
            Class.forName("com.mysql.jdbc.Driver");
            //2.获取数据库连接对象Connection。
            Connection conn = DriverManager.getConnection(url, user, password);
            //3.创建Sql语句对象Statement,填写SQL语句
            PreparedStatement preparedStatement = conn.prepareStatement("select * from t_student where `name` = ?; ");
            //传入查询参数
            preparedStatement.setString(1, "张三");
            //4.执行SQL查询,返回结果集对象ResultSet
            ResultSet resultSet = preparedStatement.executeQuery();
            List studentList = new ArrayList<>();
            //5.循环解析结果集,获取查询用户list集合
            while (resultSet.next()) {
                Student student = Student.builder()
                        .id(resultSet.getLong("id"))
                        .name(resultSet.getString("name"))
                        .age(resultSet.getInt("age"))
                        .build();
                studentList.add(student);
            }
            //打印查询结果
            System.out.println(studentList);
            //6.关闭连接,释放资源
            resultSet.close();//关闭结果集对象
            preparedStatement.close();//关闭Sql语句对象
            conn.close();//关闭数据库连接对象
        }
    }
    

    运行截图如下:

    运行截图

    这段代码主要有如下四点问题:

    1. 结果集解析复杂,列名硬编码,sql变化导致解析代码变化,系统不易维护;
    2. sql语句硬编码,数据库配置硬编码,难以维护;
    3. 频繁连接、释放数据库资源,没有用到池化思想,系统性能不高;
    4. prepareadStatement向占位符传参数存在硬编码,不易维护。

    所以我们需要一个ORM框架,来解决这些痛点。我用的最多的ORM框架是MyBatis,我们就来从源码角度来分析它,看看MyBatis是怎么解决这些问题的。

    MyBatis介绍

    什么是MyBatis

    • MyBatis是一款优秀的持久层框架,它支持自定义SQL、存储过程以及高级映射。
    • MyBatis对JDBC封装使得开发者只需要关注SQL语句与业务本身即可,无需开发者处理加载驱动、获取连接、创建Statement等繁琐的过程。
    • MyBatis可以通过简单的XML或注解来配置和映射原始类型、接口和Java POJO为数据库中的记录。
    • MyBatis是一个实现了ORM思想的持久层框架。

    什么是ORM?为什么说MyBatis是一个半ORM框架?

    • ORM:Object/Relation Mapping 对象/关系映射。
    • ORM思想:将数据库中的关系数据表映射为Java中的对象,把对数据表的操作转换为操作对象,实现面向对象编程。因此,ORM的目的是使得开发人员以面向对象的思想来操作数据库
    • MyBatis框架是一个半自动的ORM持久层框架,也可以在Java中实现类似insert(Student)的操作最终操作数据库,但是需要我们自己写SQL语句。

    MyBatis操作数据库

    项目结构截图如下:

    项目结构截图

    在resources目录下创建mybatis-config.xml文件,内容如下:

    
    configuration
            PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-config.dtd">
    <configuration>
        <environments default="development">
            <environment id="development">
                <transactionManager type="JDBC"/>
                <dataSource type="POOLED">
                    
                    <property name="driver" value="com.mysql.jdbc.Driver"/>
                    <property name="url" value="jdbc:mysql://localhost:3306/sjdwz_test?useSSL=false"/>
                    <property name="username" value="root"/>
                    <property name="password" value="1234567"/>
                dataSource>
            environment>
        environments>
        <mappers>
            
            <mapper resource="StudentMapper.xml"/>
        mappers>
    configuration>
    

    在resources目录下创建StudentMapper.xml文件,内容如下:

    
    mapper
            PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <mapper namespace="test">
        
        <select id="findListByName" resultType="com.sjdwz.db.Student" parameterType="string">
            select * from t_student where `name` = #{name};
        select>
    mapper>
    

    MyBatis操作数据库代码如下:

    package com.sjdwz.mybatis;
    
    import com.sjdwz.db.Student;
    import org.apache.ibatis.io.Resources;
    import org.apache.ibatis.session.SqlSession;
    import org.apache.ibatis.session.SqlSessionFactory;
    import org.apache.ibatis.session.SqlSessionFactoryBuilder;
    
    import java.io.IOException;
    import java.io.InputStream;
    import java.util.List;
    
    /**
     * @Description Mybatis示例
     * @Created by 随机的未知
     */
    public class MybatisTest {
        public static void main(String[] args) throws IOException {
            //1.创建SqlSessionFactoryBuilder对象
            SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
            //2.SqlSessionFactoryBuilder对象创建工厂对象
            InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
            SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream);
            //3.工厂对象Factory打开SqlSession会话
            SqlSession sqlSession = sqlSessionFactory.openSession();
            //4.SqlSession会话对象执行SQL语句,findListByName(命名空间+查询语句唯一标识)
            List studentList = sqlSession.selectList("test.findListByName","张三");
            //5.打印查询结果
            System.out.println(studentList);
            //6.关闭sqlSession会话
            sqlSession.close();
        }
    }
    
    

    运行截图如下:

    运行截图

    Mybatis配置和代码解决的问题

    在前文,使用JDBC存在四个问题,而Mybatis就解决了这四个问题。

    JDBC编码存在的第一个问题的解决

    第一个问题是结果集解析复杂,列名硬编码,sql变化导致解析代码变化,系统不易维护;

    MyBatis编码中我们不需要进行结果集解析,只需要在编码时指定sql即可,MyBatis会给我们结果;

    List studentList = sqlSession.selectList("test.findListByName","张三");
    

    JDBC编码存在的第二个问题的解决

    第二个问题是sql语句硬编码,数据库配置硬编码,难以维护;

    数据库的配置和sql语句,我们写到了xml文件,解决了硬编码的问题

    JDBC编码存在的第三个问题的解决

    第三个问题是频繁连接、释放数据库资源,没有用到池化思想,系统性能不高

    MyBatis使用了池化思想,解决了这个问题;

    JDBC编码存在的第四个问题的解决

    第三个问题是prepareadStatement向占位符传参数存在硬编码,不易维护

    我们在配置文件标签上写明了参数,并在代码中传入,避免了占位符的硬编码,解决了此问题。

    截图

    截图

    总结

    我们回顾了JDBC和MyBatis的编码方式,了解了JDBC编码存在的问题,并知道了MyBatis编码确实解决了这几个问题。

    后面我们就来分析MyBatis源码了。

  • 相关阅读:
    Pandas分组函数和聚合函数
    阶段性总结
    OpenAI新推出的Sora是什么?如何注册使用?
    JavaScript项目1_猜数字(前导)
    java基于ssm框架的学生在线考试系统
    嵌入式必学,硬件资源接口详解——基于ARM AM335X开发板 (上)
    探索 10 个有价值的在线免费设计模板网站
    如何创建像 Quora 这样的问答网站:技术堆栈、用户获取等
    3D开发工具HOOPS:助力Navisworks数据处理与3D模型可视化!
    关于iframe的页面加载出现滚动条的问题
  • 原文地址:https://www.cnblogs.com/nicaicai/p/18154248