5

MyBatis源码之前言—JDBC编码存在的问题和Mybatis的介绍 - 随机的未知

 3 weeks ago
source link: https://www.cnblogs.com/nicaicai/p/18154248
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

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<Student> 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文件,内容如下:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE 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>
        <!--        加载sql映射文件-->
        <mapper resource="StudentMapper.xml"/>
    </mappers>
</configuration>

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

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="test">
    <!--    id是指sql的唯一标识,resulttype是指返回值的类型-->
    <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<Student> studentList = sqlSession.selectList("test.findListByName","张三");
        //5.打印查询结果
        System.out.println(studentList);
        //6.关闭sqlSession会话
        sqlSession.close();
    }
}

运行截图如下:

运行截图

Mybatis配置和代码解决的问题

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

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

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

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

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

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

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

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

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

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

1306921-20240424072407057-290874420.png

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

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

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

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

截图

截图

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

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


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK