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<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编码存在的第三个问题的解决

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

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

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

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

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

截图

截图

总结

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

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/573256.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Web端Webrtc,SIP,RTSP/RTMP,硬件端,MCU/SFU融合视频会议系统方案分析

Web端视频融合&#xff0c;会议互通已经是视频会议应用的大趋势&#xff0c;一是目前企业有大量的老视频会议硬件设&#xff0c;二新业务又需要Web端支持视频会议监控直播需求&#xff0c;迫切需要一个融合对接的方案&#xff0c;即能把老的设备用起来&#xff0c;又能对接新的…

【每日刷题】Day22

【每日刷题】Day22 &#x1f955;个人主页&#xff1a;开敲&#x1f349; &#x1f525;所属专栏&#xff1a;每日刷题&#x1f34d; &#x1f33c;文章目录&#x1f33c; 1. 1669. 合并两个链表 - 力扣&#xff08;LeetCode&#xff09; 2. 11. 盛最多水的容器 - 力扣&#…

分类算法——ROC曲线与AUC指标(九)

知道TPR与FPR TPRTP/(TP FN) 所有真实类别为1的样本中&#xff0c;预测类别为1的比例 FPR FP/(FP TN) 所有真实类别为0的样本中&#xff0c;预测类别为1的比例 ROC曲线 ROC曲线的横轴就是FPRate&#xff0c;纵轴就是TPRate&#xff0c;当二者相等时&#xff0c;表示的意义…

Linux 内核设备树 ranges属性

今天有人问了我一下ranges属性&#xff0c;找了相关资料确认后&#xff0c;记录一下&#xff1a; 参考资料链接&#xff1a;让你完全理解linux内核设备树ranges属性地址转换 - vkang - 博客园 (cnblogs.com) ranges属性定义如下&#xff1a; ranges < local_address pa…

webpack面试题(持续汇总ing。。。)

webpack的编译过程 初始化 此阶段&#xff0c;webpack会将CLI参数、配置文件、默认配置进行融合&#xff0c;形成一个最终的配置对象。对配置的处理过程是依托一个第三方库 yargs 完成的。此阶段相对比较简单&#xff0c;主要是为接下来的编译阶段做必要的准备目前&#xff0c;…

三数之和 ---- 双指针

题目链接 题目: 分析: 解法一: 暴力解法, 将所有的三元组都算出来看是否为0, 题目要求去重操作, 所以我们可以使用set去重解法二: 因为我们知道当计算两数之和时, 我们使用的方法是将数组排序,然后利用"双指针"那么同理, 计算三个数之和: 1. 排序2. 固定一个数a, …

数据库管理-第176期 浅析代码团队建设(20240425)

数据库管理176期 2024-04-25 数据库管理-第176期 浅析代码团队建设&#xff08;20240425&#xff09;1 国内现状2 需求管控3 竞争与迭代总结 数据库管理-第176期 浅析代码团队建设&#xff08;20240425&#xff09; 作者&#xff1a;胖头鱼的鱼缸&#xff08;尹海文&#xff09…

安卓Activity的setContentView()流程分析

目录 前言一、Activity的视图加载过程1.1 视图结构1.2 流程分析1.2.1 Activity.java -->setContentView()1.2.2 Activity.java -->getWindow()1.2.3 PhoneWindow.java -->setContentView()1.2.4 PhoneWindow.java --->installDecor()1.2.4.1 PhoneWindow.java ---&…

Yolov5 export.py实现onnx模型的导出

查了很多资料&#xff0c;很多用python代码写的&#xff0c;只需要这个库那个库的&#xff0c;最后都没成功。 不如直接使用Yolov5里面的 export.py实现模型的转换。 一&#xff1a;安装依赖 因为yolov5里面的requirments.txt是将这些转换模型的都注释掉了 所以需要解除注释…

SpringCloud alibaba整合OpenFeign

目录 一、为什么使用OpenFeign 二、准备两个服务 三、最简单使用- 返回字符串 ①引入openfeign依赖 ②调用端在启动类上添加EnableFeignClients注解 ③在被调用端写一个简单的接口 ④在调用端新建一个service类 专门用于远程调用 ​编辑 ⑤ 在调用端写一个conteoller …

翻译《The Old New Thing》 - What does SHGFI_USEFILEATTRIBUTES mean?

What does SHGFI_USEFILEATTRIBUTES mean? - The Old New Thing (microsoft.com)https://devblogs.microsoft.com/oldnewthing/20040601-00/?p39073 Raymond Chen 2004年06月01日 在使用 SHGetFileInfo 函数时&#xff0c;你可以设置一个名为 SHGFI_USEFILEATTRIBUTES 的标志…

绿联搭建rustdesk服务器

绿联搭建rustdesk服务器&#xff0c;不再使用向日葵 注意&#xff1a;本服务器需要有动态公网IP以及自己的域名&#xff0c;ipv6未测试。 1. 拉取镜像 rustdesk/rustdesk-server-s6:latest 注意是这个-s6的镜像。 2. 部署镜像 2.1 内存配置 本服务器比较省内存&#xff0…

区块链安全应用-------压力测试

基于已有的链进行测试&#xff08;build_chain默认建的链 四个节 点&#xff09;&#xff1a; 第一步&#xff1a;搭链 1. 安装依赖 在ubuntu操作系统中&#xff0c;操作步骤如下&#xff1a; sudo apt install -y openssl curl 2. 创建操作目录, 下载安装脚本 ## 创建操作…

力扣数据库题库学习(4.22日)

577. 员工奖金 问题链接 思路分析 Employee表与Bonus表通过empId字段可以连接&#xff0c;需求是查出奖金少于1000的员工名和奖金值。 这里奖金少于1000的情况就是没有奖金有奖金但少于1000 这里我给出的解决方案就是使用左连接&#xff0c;将Employee表作为左表&#xff…

js的算法-交换排序(冒泡)

交换排序 所谓交换排序&#xff0c;是指根据序列中两个元素关键字的比较结果来对换这两个记录在序列中的位置。基于交换的排序算法很多&#xff0c;本次介绍冒泡排序和快速排序。 冒泡 基本思想 从后往前&#xff08;或从前往后&#xff09;两两比较相邻元素的值&#xff0…

Nginx第3篇-使用ngx_http_proxy_connect_module配置https正向代理

场景 我使用python爬虫&#xff0c;然后需要个代理&#xff0c;所以就用Nginx搭了一个代理服务器。对Nginx也不太熟&#xff0c;慢慢摸索&#xff0c;搭建完之后发现只能代理http的请求&#xff0c;无法穿透https。几经折腾和摸索发现一个强大的HTTP代理模块&#xff1a;ngx_h…

泛微OA对接北森HR系统场景解析

随着企业信息化建设的深入推进&#xff0c;跨系统集成已成为提升管理效率、实现数据一体化的关键举措。详细阐述其如何通过泛微OA&#xff08;Office Automation&#xff09;系统与北森HR&#xff08;Human Resource&#xff09;系统的深度对接&#xff0c;实现人员信息、员工请…

RIP最短路实验(思科)

华为设备参考&#xff1a;RIP最短路实验&#xff08;华为&#xff09; 一&#xff0c;技术简介 RIP&#xff08;Routing Information Protocol&#xff0c;路由信息协议&#xff09;是一种基于距离矢量的内部网关协议&#xff0c;工作原理是每个路由器周期性地向邻居路由器发…

深度解析 Spring 源码:揭秘BeanFactory 之谜

文章目录 一、认识BeanFactory1.1 BeanFactory的概述1.2 BeanFactory与 ApplicationContext的区别 二、BeanFactory源码解读2.1 BeanFactory 接口2.1.1 getBean()2.1.2 containsBean()2.1.3 isSingleton() 2.2 DefaultListableBeanFactory 类2.2.1 registerBeanDefinition()2.2…

游戏行业干货科普 | 各个诚实都有哪些游戏公司?

本文主要列举上海、北京、广州、深圳、成都、杭州等城市游戏公司名称&#xff0c;大家可以码住&#xff0c;慢慢看~ 上海 米哈游 游戏势力新一极&#xff0c;近十年唯一一家打破腾讯、网易二强局面的公司莉莉丝 卡牌自研头部&#xff0c;SLG发行头部&#xff0c;最懂商业化的…