自己动手实现mybatis的底层框架(不用动态代理直接用执行器、用动态代理自己实现。图文分析!)
目录
一.原生mybits框架图分析
自己实现Mybatis框架的分析
两种框架操作数据库的方法:
二.搭建开发环境
1.先创建一个maven项目
2.加入依赖(mysql dom4j junit lombok)
三.mybatis框架的设计思路
具体实现过程
3.1实现任务阶段 1- 完成读取配置文件,得到数据库连
3.2实现任务阶段 2- 编写执行器,输入 SQL 语句,完成操作
3.3实现任务阶段 3- 将 Sqlsession 封装到执行器
实现方法二:用动态代理来实现
一.原生mybits框架图分析

1) mybatis 的核心配置文件mybatis-config.xml: 进行全局配置,全局只能有一个这样的配置文件XxxMapper.xml 配置多个 SQL ,可以有多个 XxxMappe.xml 配置文件2) 通过 mybatis-config.xml 配置文件得到 SqlSessionFactory3) 通过 SqlSessionFactory 得到 SqlSession ,用 SqlSession 就可以操作数据了4) SqlSession 底层是 Executor( 执行器 ), 有 2 重要的实现类 , 有很多方法。调用sqlsession原生的操作DB的方法,实际上就是调用Executor的方法。
我们从mybatis的jar包中看到其中有个Executor执行器的包,里面封装了很多操作数据库的方法

CachingExecutor类实现了Executor接口:
很多关于DB的原生方法都在此类进行一个实现:比如query / select / update / delete 方法等


自己实现Mybatis框架的分析
引用老韩博主的图

两种框架操作数据库的方法:
@1: 首先我们不通过代理对象操作DB的方法。而是直接通过执行器去操作DB

我们首先会自定义核心配置文件(XML文件):1.这里面包括数据库的连接 ,我们会用一个snConfigration配置类,去读取properties文件,并建立与数据库的连接。
然后 通过snExecutor执行器类,直接去执行DB的查找方法,并自动返回一个Monster对象。
这里面,我们会定义一个Executor接口,里面定义关于操作数据库的CRUD方法,这里只采用query方法。执行器得到snConfiguration建立的与数据库的连接,然后采用query方法操作数据库,并返回一个对象。
@2:其次就是采用mybatis的代理对象去操作DB数据库。

我们之前直接用执行器的方法,并没有使用到我们的Mapper.xml文件。总所周知
Monster类对应的就是数据库中的一个Monster表,MonsterMapper接口就是对这个表进行操作的方法的定义,MonsterMapper.xml文件就是对这个接口的方法具体的实现。
那我们怎么将两者结合在一起呢,他们之间有个MapperBean类,这个类可以将XML文件中的SQL语句的方法进行封装这里我们用Functions进行,以及封装属性:XML文件所对应的这个接口的名字。 这个类的作用就是在之后的动态代理对象中,我们调用该对象的query()方法

二.搭建开发环境
1.先创建一个maven项目

2.加入依赖(mysql dom4j junit lombok)
lombok:可以用来简化javabean/pojo的开发(包括getter和setter方法以及构造器等)
解析一些lombok如何简化pojo的开发的:使用注解的形式帮我们写了其中的getter setter无参构造与有参构造以及toString方法。比如@Getter就会将所有的属性的Getter方法给构造出来,方便实用。
其中@Data注解能够生成更多东西,可以看看源码
里面默认有有参构造器,但是加入了@AllAragsConstructor@Data里面的无参构造器就没有了。
如图进行比较

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.sn</groupId><artifactId>sn-mybatis</artifactId><version>1.0-SNAPSHOT</version><properties><maven.compiler.source>11</maven.compiler.source><maven.compiler.target>11</maven.compiler.target><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding></properties><!--引入必要的依赖--><dependencies><!--引入dom4j--><dependency><groupId>dom4j</groupId><artifactId>dom4j</artifactId><version>1.6.1</version></dependency><!--引入mysql依赖--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.49</version></dependency><!--lombok-简化entity/javabean/pojo开发 --><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.4</version></dependency><!--junit依赖--><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version></dependency></dependencies></project>
三.mybatis框架的设计思路
具体实现过程
3.1实现任务阶段 1- 完成读取配置文件,得到数据库连
sn_mybatis
用sn_mybatis来代替原生的mybatis-config.xml文件
:里面存放的依然是连接数据库的相关配置信息。
<?xml version="1.0" encoding="UTF-8" ?>
<database>
<!--配置连接数据库的必要的信息--><property name="driverClassName" value="com.mysql.jdbc.Driver"/><property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=true&useUnicode=true&characterEncoding=UTF-8"/><property name="username" value="root"/><property name="password" value="ygd"/>
</database>
snConfiguration
snConfiguration类:是为了代替mybatis-config.xml文件的configuration标签中的一部分作用:其作用是解析对应的XML文件,和数据库建立连接。
几个重要的点:@1.需要通过类加载器,将xml文件以文件流的形式读入
@2.运用dom4j中XML解析技术,对该XML文件流进行解析
@3.获取XML配置文件中对应的键值对,创建驱动,建立与数据库的连接
package com.sn.sqlsession;import com.mysql.jdbc.Connection;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;import java.io.InputStream;
import java.sql.DriverManager;/*** @author ygd* 读取xml文件,建立连接*/
public class snConfiguration {//定义类的加载器(将xml文件进行加载,得到一个文件流)private static ClassLoader loader = ClassLoader.getSystemClassLoader();//读取xml文件,并进行处理public Connection build(String resource){Connection connection = null;try {//先加载配置文件,获取到对应的inputStreamInputStream stream = loader.getResourceAsStream(resource);//dom4j=>用来解析xml文件的SAXReader reader = new SAXReader();//返回一个文档类型Document document = reader.read(stream);//获取到配置文件的根元素Element root = document.getRootElement();//根据解析的root的元素返回一个connectonSystem.out.println("root=="+root);connection = evalDataSource(root);return connection;} catch (Exception e) {throw new RuntimeException(e);}}//这个方法会解析sn_config.xml文件,并返回Connectionprivate Connection evalDataSource(Element node){if(!"database".equals(node.getName())){throw new RuntimeException("root的节点应该是<database>");}//连接DB的必要参数String driverClassName = null;String url = null;String username = null;String password = null;//遍历node下的子节点,获取属性值for (Object item : node.elements("property")) {Element i = (Element) item;//i 就是 对应property节点String name = i.attributeValue("name");String value = i.attributeValue("value");//判断是否得到name 和 valueif (name == null || value == null) {throw new RuntimeException("property 节点没有设置name或者value属性");}switch (name) {case "url":url = value;break;case "username":username = value;break;case "driverClassName":driverClassName = value;break;case "password":password = value;break;default:throw new RuntimeException("属性名没有匹配到...");}}java.sql.Connection connection = null;try {//使用原生的JDBC来连接数据库//建立驱动Class.forName(driverClassName);//建立连接connection = DriverManager.getConnection(url,username,password);} catch (Exception e) {e.printStackTrace();}return (Connection) connection; //返回Connection}}
3.2实现任务阶段 2- 编写执行器,输入 SQL 语句,完成操作
在通过自己配置的mybaties-config.xml文件获取到与数据库的连接之后,接下来的操作:通过获取的连接,让执行器Executor执行对应的sql语句,操作DB。
Executor接口
package com.sn.sqlsession;/*** @version 1.0*/
public interface Executor {//泛型方法//statement就是sql语句//parameter就是参数public <T> T query(String statement, Object parameter);
}
SnExecutor类
package com.sn.sqlsession;import com.sn.entity.Monster;import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;/*** @author sn* 这里是实现对数据库DB的直接操作*/
public class SnExecutor implements Executor{//这里的Statement就是sql语句,parameter就是传入的参数private snConfiguration snConfiguration =new snConfiguration();/*** 根据 sql 查找结果** @param sql* @param parameter* @param <T>* @return*/@Override//这里只用query操作来对数据库进行相应的处理。public <T> T query(String sql, Object parameter) {//得到连接Connection,采用的是自定义的方法Connection connection = getConnection();//查询返回的结果集ResultSet set = null;PreparedStatement pre = null;try {pre = connection.prepareStatement(sql);//设置参数, 如果参数多, 可以使用数组处理.pre.setString(1, parameter.toString());set = pre.executeQuery();//把set数据封装到对象-monster//这里做了简化处理//认为返回的结果就是一个monster记录//完善的写法是一套反射机制.Monster monster = new Monster();//遍历结果集, 把数据封装到monster对象while (set.next()) {monster.setId(set.getInt("id"));monster.setName(set.getString("name"));monster.setEmail(set.getString("email"));monster.setAge(set.getInt("age"));monster.setGender(set.getInt("gender"));monster.setBirthday(set.getDate("birthday"));monster.setSalary(set.getDouble("salary"));}return (T) monster;} catch (Exception throwables) {throwables.printStackTrace();} finally {try {if (set != null) {set.close();}if (pre != null) {pre.close();}if (connection != null) {connection.close();}} catch (Exception throwables) {throwables.printStackTrace();}}return null;}//编写方法,通过snConfiguration对象,返回连接private Connection getConnection() {Connection connection =snConfiguration.build("sn_mybatis.xml");return connection;}
}
3.3实现任务阶段 3- 将 Sqlsession 封装到执行器
瞧瞧SqlSession自己的方法:

可以看出DefaultSqlSession封装了执行器以及和XML中的配置信息相关的类。

以及DefaultsqlSession自己对数据库操作的方法。
DefaultsqlSession实际上是实现了SqlSession的这个接口
SnSqlSession
package com.sn.sqlsession;/*** @author sn* sqlsession主要封装数据的链接Configuration和Executor执行器* 以及操作DB的一些自己的方法*/
public class SnSqlSession {//封装执行器private Executor executor = new SnExecutor();//配置private snConfiguration snConfiguration = new snConfiguration();//编写selectOne方法,并且返回一条记录public <T> T selectOne(String statement,Object parameter){return executor.query(statement,parameter);}
}
执行一个测试方法

我们在使用sqlSession的selectOne可以知道,实际上调用的是其中的Executor执行器的方法,来对数据库进行一个操作
如图底层是调用的Executor的方法进行一个调用。
这三个任务阶段就实现了:如何读取核心配置文件XML,得到数据库的连接, 并通过Executor执行器去执行数据的CURD操作。
实现方法二:用动态代理来实现
接下来就是对mybatis框架中Mapper接口方法的声明。XXMapper.xml文件实现的接口方法,框架中是如何去实现这些方法的呢?

如上图所示
以前的接口方法的实现,是通过实现该接口的类进行实现的。 而mybatis框架中:
一个类------数据库中的一个表。
类Mapper接口 -------- 操作这个表的方法的声明。
类Mapper.xml -------- 对操作表方法的实现。
其实在接口和XML文件之间有一个MapperBean对象。现在只需知道这个MapperBean对象对后面动态代理生成对象起作用。在这个MapperBean对象中有
Function类:主要是记录XML文件中方法的各种信息,比如select,delete,update等以及返回的类型,参数的类型等。
List<Function>集合,用户来存放不同的方法
String interfaceName:用来存放对应Mapper接口的名称
Function方法:
package com.sn.config;import lombok.Getter;
import lombok.Setter;/*** @author sn* 记录对应的mapper的方法信息*/
@Getter
@Setter
public class Function {//属性private String sqlType; //sql类型,比如crudprivate String funcName; //记录的方法名private String sql;//记录对应的sql语句private Object resultType;//记录一个返回类型private String parameter;//这个是我们的参数类型}
MapperBean方法
package com.sn.config;import lombok.Getter;
import lombok.Setter;import java.util.List;/*** @author sn* MapperBean对象就是封装Mapper的信息。* 1:对应相应的接口信息* 2:封装对应mapper.xml的信息,这些信息用Function来抽象。*/
@Setter
@Getter
public class MapperBean {private String interfaceName; //接口名//接口下的所有的方法private List<Function> functions;}
MonsterMapper
package com.sn.mapper;import com.sn.entity.Monster;/*** @author sn* MonsterMapper:声明DB的crud方法*/
public interface MonsterMapper {//查询方法public Monster getMonsterById(Integer id);
}
代理对象类
package com.sn.sqlsession;import com.sn.config.Function;
import com.sn.config.MapperBean;import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.nio.file.WatchService;
import java.util.List;/*** @author sn* 动态代理生成Mapper对象,并调用snExecutor方法*/
public class snMapperProxy implements InvocationHandler {//属性private SnSqlSession sqlSession;private String mapperFile;private snConfiguration snConfiguration;//构造器//最后一个参数传进来的是一个接口public snMapperProxy(snConfiguration snConfiguration, SnSqlSession sqlSession, Class clazz) {this.snConfiguration = snConfiguration;this.sqlSession = sqlSession;this.mapperFile = clazz.getSimpleName() + ".xml";}//实现一个动态代理的机制//当执行到Mapper接口的代理对象的方法的时候,会执行invoke方法@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {//首先通过XML文件获取MapperBean对象(接口名。接口下面的方法)MapperBean mapperBean = snConfiguration.readMapper(mapperFile);//判断是否是XMl文件对应的接口//通过method方法得到声明这个方法的接口的名字if (!method.getDeclaringClass().getName().equals(mapperBean.getInterfaceName())) {return null;}//取出mapperBean的functionsList<Function> functions = mapperBean.getFunctions();//先判断当前的这个mapperBean解析对应的XML文件中有方法if(null != functions && 0 != functions.size()){for (Function function : functions) {//当前要执行的方法和Function的方法一致,说明我们可以//去当前遍历的function对象中,取出相应的信息,并执行相应的方法if(method.getName().equals(function.getFuncName())){//如果我们当前的function执行的sqlType是select//我们就去执行selectOne()等~if("select".equalsIgnoreCase(function.getSqlType())){return sqlSession.selectOne(function.getSql(),String.valueOf(args[0]));}}}}return null;}
}
测试
@Testpublic void test2(){SnSqlSessionFactor snSqlSessionFactor = new SnSqlSessionFactor();SnSqlSession snSqlSession = snSqlSessionFactor.openSession();MonsterMapper mapper = snSqlSession.getMapper(MonsterMapper.class);Monster monster = mapper.getMonsterById(2);System.out.println("monster"+monster);}

这个后序的用动态代理着实有点不明白,但是代码都是对的,大佬们可以自行理解
相关文章:
自己动手实现mybatis的底层框架(不用动态代理直接用执行器、用动态代理自己实现。图文分析!)
目录 一.原生mybits框架图分析 自己实现Mybatis框架的分析 两种框架操作数据库的方法: 二.搭建开发环境 1.先创建一个maven项目 2.加入依赖(mysql dom4j junit lombok) 三.mybatis框架的设计思路 具体实现过程 3.1实现任务阶段 1- 完成读取配置文件&#x…...
项目日志——日志落地模块的设计、实现、测试
文章目录 日志落地模块设计实现扩展实现测试 日志落地模块 设计 功能是,将格式化完成后的日志消息字符串,输出到指定的位置 支持将日志落地到不同的位置 标准输出指定文件滚动文件 滚动文件按照时间或者大小进行滚动切换,可以按照天数对…...
CTK框架(七):事件监听
目录 1.概述 2.监听接口 3.具体实现 1.概述 CTK(Common Toolkit)框架中的事件监听机制是一个重要的功能,它允许开发者在特定事件发生时接收到通知并执行相应的操作。CTK框架主要支持三种类型的事件监听:框架事件、插件事件和服…...
一区霜冰算法+双向深度学习模型+注意力机制!RIME-BiTCN-BiGRU-Attention
一区霜冰算法双向深度学习模型注意力机制!RIME-BiTCN-BiGRU-Attention 目录 一区霜冰算法双向深度学习模型注意力机制!RIME-BiTCN-BiGRU-Attention效果一览基本介绍程序设计参考资料 效果一览 基本介绍 1.Matlab实现RIME-BiTCN-BiGRU-Attention霜冰算法…...
C语言 | Leetcode C语言题解之第396题旋转函数
题目: 题解: #define MAX(a, b) ((a) > (b) ? (a) : (b))int maxRotateFunction(int* nums, int numsSize){int f 0, numSum 0;for (int i 0; i < numsSize; i) {f i * nums[i];numSum nums[i];}int res f;for (int i numsSize - 1; i &g…...
利士策分享,克服生活中的困难:走好勇攀高峰的每一步
利士策分享,克服生活中的困难:走好勇攀高峰的每一步 在这个纷繁复杂的世界里,每个人都是自己生命旅程中的行者,而生活,则是一条既铺满鲜花又布满荆棘的道路。 我们或许会在某个清晨醒来,发现自己正站在一座…...
PurchasereturnController
目录 1、 PurchasereturnController 1.1、 反审核退货单 1.1.1、 //配件ID 1.1.2、 //配件编码 1.1.3、 //修改后仓库 1.1.4、 //修改配件信息表库存量 PurchasereturnController using QXQPS.Models; using QXQPS.Vo; using System; using System.Collection…...
mysql 学习笔记 八
总结 自动提交 查看自动提交状态:SELECT AUTOCOMMIT ; 设置自动提交状态:SET AUTOCOMMIT 0 。 手动提交 AUTOCOMMIT 0 时,使用 COMMIT 命令提交事务。 事务回滚 AUTOCOMMIT 0 时,使用 ROLLBACK 命令回滚事务。 …...
反序列化漏洞练习2
拿到题目,发现目标是获得flag.php的内容,且sis中admin和passwd等于sis2407时会输出fag的内容 根据源码编写序列化代码 <?php error_reporting(0); class sis{public $admin;public $passwd;public function __construct(){$this->admin "sis2407"…...
基于SpringBoot的社区医院管理系统
作者:计算机学姐 开发技术:SpringBoot、SSM、Vue、MySQL、JSP、ElementUI等,“文末源码”。 专栏推荐:前后端分离项目源码、SpringBoot项目源码、SSM项目源码 系统展示 基于JavaSpringBootVueMySQL的社团管理系统【附源码文档】、…...
YOLOv8安装配置教程(Windows版)
YOLOv8安装配置教程(Windows版) 简介:最近由于选择了人工智能方向的专业选修课,课程需要安装配置YOLOv8,经过查阅各种资料后才发现,许多教程都比较老旧,并且文件位置也发生了变化,所…...
Linux的历史,版本,Linux的环境安装、简单学习4个基本的Linux指令等的介绍
文章目录 前言一、Linux的历史二、版本三、Linux的环境安装1. 腾讯云服务器的申请2. xshell的安装与使用 四、 简单学习4个基本的Linux指令1. ls2. pwd3. mkdir4. cd 总结 前言 Linux的历史,版本,Linux的环境安装、简单学习4个基本的Linux指令等的介绍 …...
【论文阅读】01-Survey on Temporal Knowledge Graph
原文名称:Survey on Temporal Knowledge Graph 1 Introduction 目前有两种方法:基于距离模型的嵌入变换方法和基于语义匹配模型的双线性模型。它们的思想都是将包含实体和关系的知识图谱嵌入到连续的低纬度实向量空间中 时间知识图的推理有两种,第一种是…...
【AIGC】InstructPixPix:基于文本引导的图像编辑技术
github:diffusers/examples/instruct_pix2pix/train_instruct_pix2pix_sdxl.py at main huggingface/diffusers GitHub 论文:https://arxiv.org/pdf/2211.09800 摘要 我们提出了一种从人类指令编辑图像的方法:给定一个输入图像和告诉模型做什么的书面…...
无人机动力系统设计之桨叶推力计算
无人机动力系统设计之桨叶推力计算 1. 源由2. 关键参数2.1 特性参数2.1.1 材质(Material)2.1.2 叶片数量(Number of Blades)2.1.3 重量(Weight)2.1.4 噪音水平(Noise Level) 2.2 安装…...
LabVIEW重构其他语言开发的旧系统
在面对一个运行已久、代码不清晰的项目时,如果该项目涉及复杂的通讯协议(如串口和488通讯),重新开发并优化成LabVIEW版本可以极大提升系统的易用性和维护性。为了确保通讯协议的顺利解析和移植,借助专业工具分析现有通…...
[晕事]今天做了件晕事43 python-byte串长度与转义字符
今天办了一件晕事,导致测试结果与预期不一致。 过程是,组装byte串的时候,整个字符串里有转义字符\x0d。 from scapy.all import IPv6, UDP pkt IPv6(src"2002:db8:a0b:12f0::157", dst"2002:db8:a0b:12f0::13")/UDP(sp…...
初识redis(String,Hash,List,Set,SortedSet)
认识NoSql sql关系型数据库 nosql非关系型数据库 nosql具有非结构化,Key/Value,Document,Draph 无关联的,非sql,BASE(原子性,持久性,一致性,隔离性) 认识r…...
Ton与ETH的一些独特的区别
文章目录 前言一、智能合约需要收取租金。二、从数据到大数据的转变三、智能合约不能运行其他合约的getter方法四、合约不是无法改变的五、Ton取消了无限制的数据结构六、钱包和地址具有独立性 前言 TON区块链是一个现代化的区块链,它为智能合约开发带来了一些全新…...
C++ | Leetcode C++题解之第396题旋转图像
题目: 题解: class Solution { public:int maxRotateFunction(vector<int>& nums) {int f 0, n nums.size();int numSum accumulate(nums.begin(), nums.end(), 0);for (int i 0; i < n; i) {f i * nums[i];}int res f;for (int i …...
第19节 Node.js Express 框架
Express 是一个为Node.js设计的web开发框架,它基于nodejs平台。 Express 简介 Express是一个简洁而灵活的node.js Web应用框架, 提供了一系列强大特性帮助你创建各种Web应用,和丰富的HTTP工具。 使用Express可以快速地搭建一个完整功能的网站。 Expre…...
Prompt Tuning、P-Tuning、Prefix Tuning的区别
一、Prompt Tuning、P-Tuning、Prefix Tuning的区别 1. Prompt Tuning(提示调优) 核心思想:固定预训练模型参数,仅学习额外的连续提示向量(通常是嵌入层的一部分)。实现方式:在输入文本前添加可训练的连续向量(软提示),模型只更新这些提示参数。优势:参数量少(仅提…...
练习(含atoi的模拟实现,自定义类型等练习)
一、结构体大小的计算及位段 (结构体大小计算及位段 详解请看:自定义类型:结构体进阶-CSDN博客) 1.在32位系统环境,编译选项为4字节对齐,那么sizeof(A)和sizeof(B)是多少? #pragma pack(4)st…...
Day131 | 灵神 | 回溯算法 | 子集型 子集
Day131 | 灵神 | 回溯算法 | 子集型 子集 78.子集 78. 子集 - 力扣(LeetCode) 思路: 笔者写过很多次这道题了,不想写题解了,大家看灵神讲解吧 回溯算法套路①子集型回溯【基础算法精讲 14】_哔哩哔哩_bilibili 完…...
微信小程序 - 手机震动
一、界面 <button type"primary" bindtap"shortVibrate">短震动</button> <button type"primary" bindtap"longVibrate">长震动</button> 二、js逻辑代码 注:文档 https://developers.weixin.qq…...
对WWDC 2025 Keynote 内容的预测
借助我们以往对苹果公司发展路径的深入研究经验,以及大语言模型的分析能力,我们系统梳理了多年来苹果 WWDC 主题演讲的规律。在 WWDC 2025 即将揭幕之际,我们让 ChatGPT 对今年的 Keynote 内容进行了一个初步预测,聊作存档。等到明…...
【Java_EE】Spring MVC
目录 Spring Web MVC 编辑注解 RestController RequestMapping RequestParam RequestParam RequestBody PathVariable RequestPart 参数传递 注意事项 编辑参数重命名 RequestParam 编辑编辑传递集合 RequestParam 传递JSON数据 编辑RequestBody …...
【C语言练习】080. 使用C语言实现简单的数据库操作
080. 使用C语言实现简单的数据库操作 080. 使用C语言实现简单的数据库操作使用原生APIODBC接口第三方库ORM框架文件模拟1. 安装SQLite2. 示例代码:使用SQLite创建数据库、表和插入数据3. 编译和运行4. 示例运行输出:5. 注意事项6. 总结080. 使用C语言实现简单的数据库操作 在…...
【RockeMQ】第2节|RocketMQ快速实战以及核⼼概念详解(二)
升级Dledger高可用集群 一、主从架构的不足与Dledger的定位 主从架构缺陷 数据备份依赖Slave节点,但无自动故障转移能力,Master宕机后需人工切换,期间消息可能无法读取。Slave仅存储数据,无法主动升级为Master响应请求ÿ…...
JVM虚拟机:内存结构、垃圾回收、性能优化
1、JVM虚拟机的简介 Java 虚拟机(Java Virtual Machine 简称:JVM)是运行所有 Java 程序的抽象计算机,是 Java 语言的运行环境,实现了 Java 程序的跨平台特性。JVM 屏蔽了与具体操作系统平台相关的信息,使得 Java 程序只需生成在 JVM 上运行的目标代码(字节码),就可以…...
