Mr. Cappuccino的第57杯咖啡——简单手写Mybatis大致原理
简单手写Mybatis大致原理
- 大致原理
- 项目结构
- 项目代码
- 代码测试
大致原理
底层基于JDK动态代理技术实现
项目结构
项目代码
pom.xml
<?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</groupId><artifactId>mybatis-jdk-proxy</artifactId><version>1.0-SNAPSHOT</version><build><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><configuration><source>8</source><target>8</target></configuration></plugin></plugins></build><dependencies><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.18</version></dependency></dependencies></project>
config.properties
driverClass=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://127.0.0.1:3306/db_mybatis?serverTimezone=UTC
user=root
password=admin
UserEntity.java
package com.mybatis.entity;/*** @author honey* @date 2023-07-26 15:29:38*/
public class UserEntity {private Integer id;private String name;@Overridepublic String toString() {return "UserEntity{" +"id=" + id +", name='" + name + '\'' +'}';}
}
UserMapper.java
package com.mybatis.mapper;import com.mybatis.proxy.Insert;/*** @author honey* @date 2023-07-26 21:04:23*/
public interface UserMapper {/*** 新增用户** @return int*/@Insert("INSERT INTO `tb_user` (`id`, `name`) VALUES (null, 'Faker');")int insertUser();
}
Insert.java
package com.mybatis.proxy;import java.lang.annotation.*;/*** @author honey* @date 2023-07-27 20:48:38*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Insert {String value();
}
JdbcUtils.java
package com.mybatis.proxy;import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.Properties;/*** @author honey* @date 2023-07-27 20:57:08*/
public class JdbcUtils {private JdbcUtils() {}private static String url;private static String user;private static String password;static {try {InputStream resourceAsStream = JdbcUtils.class.getClassLoader().getResourceAsStream("config.properties");Properties properties = new Properties();properties.load(resourceAsStream);String driverClass = properties.getProperty("driverClass");url = properties.getProperty("url");user = properties.getProperty("user");password = properties.getProperty("password");Class.forName(driverClass);} catch (Exception e) {e.printStackTrace();}}public static Connection getConnection() {try {return DriverManager.getConnection(url, user, password);} catch (Exception e) {e.printStackTrace();return null;}}public static void closeConnection(ResultSet resultSet, Statement statement, Connection connection) {try {if (resultSet != null) {resultSet.close();}if (statement != null) {statement.close();}if (connection != null) {connection.close();}} catch (Exception e) {e.printStackTrace();}}public static void closeConnection(Statement statement, Connection connection) {closeConnection(null, statement, connection);}
}
MapperProxy.java
package com.mybatis.proxy;import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.sql.Connection;
import java.sql.PreparedStatement;/*** @author honey* @date 2023-07-27 20:17:23*/
public class MapperProxy implements InvocationHandler {private final Class<?> mapperClass;public MapperProxy(Class<?> mapperClass) {this.mapperClass = mapperClass;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {// 使用Java反射技术获取该方法上的注解Insert declaredAnnotation = method.getDeclaredAnnotation(Insert.class);String insertSql = declaredAnnotation.value();// 执行sql语句Connection connection = JdbcUtils.getConnection();PreparedStatement preparedStatement = connection.prepareStatement(insertSql);return preparedStatement.executeUpdate();}public <T> T getProxy() {return (T) Proxy.newProxyInstance(mapperClass.getClassLoader(), new Class[]{mapperClass}, this);}
}
SqlSession.java
package com.mybatis.proxy;/*** @author honey* @date 2023-07-27 21:10:30*/
public class SqlSession {public static <T> T getMapper(Class<T> type) {return new MapperProxy(type).getProxy();}
}
MybatisTest.java
package com.mybatis.test;import com.mybatis.mapper.UserMapper;
import com.mybatis.proxy.SqlSession;/*** @author honey* @date 2023-07-26 15:26:48*/
public class MybatisTest {public static void main(String[] args) {System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");UserMapper userMapper = SqlSession.getMapper(UserMapper.class);int result = userMapper.insertUser();System.out.println(result);}
}
代码测试
运行MybatisTest类
SqlSession.java
MapperProxy.java
MybatisTest.java
MapperProxy.java
MybatisTest.java
运行结果
相关文章:

Mr. Cappuccino的第57杯咖啡——简单手写Mybatis大致原理
简单手写Mybatis大致原理 大致原理项目结构项目代码代码测试 大致原理 底层基于JDK动态代理技术实现 项目结构 项目代码 pom.xml <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns…...

机房环境、动力、网络、安防,帮您提高运维效率,确保机房安全
机房作为单位的核心部门,由计算机、服务器、网络设备、存储设备等关键设备组成,智能化计算机机房这个概念在各个领域中,已经占据了很重要的地位,伴随着国家大力倡导的,东数西算,数字经济、云计算、5G大数据…...
大数据课程E1——Flume的概述
文章作者邮箱:yugongshiye@sina.cn 地址:广东惠州 ▲ 本章节目的 ⚪ 了解Ganglia的概念; ⚪ 了解Ganglia的拓扑结构和执行流程; ⚪ 掌握Ganglia的安装操作; 一、简介 1. 概述 1. Flume原本是由Cloudera公司开发的后来贡献给了Apache的一套分布式的、可…...
01.Redis实现发送验证码
学习目标: 提示:学习如何利用Redis来实现发送验证码功能 学习产出: 1. 准备pom环境 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId><…...
Vue中对组件的调用
在Vue中,你可以在一个页面中调用其他组件,以实现组件的复用和组合效果。以下是在Vue中实现调用页面组件的几种常见方法之一: 1.使用Vue的组件标签: 你可以在Vue的模板中使用已注册的组件标签,以调用和渲染其他组件。首…...

SpringCloud Gateway获取请求响应body大小
前提 本文获取请求、响应body大小方法的前提 : 网关只做转发逻辑,不修改请求、相应的body内容。 SpringCloud Gateway内部的机制类似下图,HttpServer(也就是NettyServer)接收外部的请求,在Gateway内部请求将会通过Htt…...

二叉树的层序遍历
给你二叉树的根节点 root ,返回其节点值的 层序遍历 。 (即逐层地,从左到右访问所有节点) 。 示例 1: 输入:root [3,9,20,null,null,15,7] 输出:[[3],[9,20],[15,7]]示例 2: 输入…...

Spring Boot 集成 Thymeleaf 模板引擎
Spring Boot 集成 Thymeleaf 模板引擎 1. Thymeleaf 介绍 Thymeleaf 是适用于 Web 和独立环境的现代服务器端 Java 模板引擎。 Thymeleaf 的主要目标是为开发工作流程带来优雅的自然模板,既可以在浏览器中正确显示的 HTML,也可以用作静态原型ÿ…...
如何快速找到合适的工作?
前面好几篇文章都在写面试的感悟,带大家了解了目前的一些市场行情,以及面试过程中招聘方与求职者看待面试的不同视角。 今天这篇文章写一些对大家求职面试可能更有用的几条建议: 第一,值与量的权衡 在早些年,大多数…...
Elasticsearch入门用例
快速开始 使用版本:V7.12 资料来自官方文档 本指南幫助初學者學習如何: 將數據添加到 Elasticsearch 搜索和排序數據 在搜索過程中從非結構化內容中提取字段 测试运行: http://localhost:9200 响应: {"name": &qu…...

python制作超炫流星雨表白,python好看的流星雨代码
大家好,本文将围绕python制作超炫流星雨表白展开说明,python好看的流星雨代码是一个很多人都想弄明白的事情,想搞清楚html流星雨代码可复制需要先了解以下几个事情。 本文讲述了Python代码示例:实现流星雨特效!具有很好…...

iOS数字转为图片
根据数字,转成对应的图片 - (void)viewDidLoad {[super viewDidLoad];[self testNum2String:10086]; }/// 根据数字,显示对应的图片 数字用特定的图片显示 - (void)testNum2String:(NSInteger)num {UIView *numContentView [[UIView alloc] initWithFr…...

mac cli文件管理器
背景 最近研究了一下在控制台查看文件的插件ranger, 官方的解释是:一个cli下的文件管理器。觉得效果也很酷炫,所以在此展示一下。 安装 brew install ranger配置生成 建议第一次使用的时候使用 ranger --copy-configall将会在~/.config/ranger目录输…...

不同语言操作符的优先级
看到标题,可能会心生疑惑: 这么基础且重要的操作,不同语言不应该是一致的吗? 并不一定,比如对于右移运算和加法运算,Go就与其他多数语言表现得不一致: Go: package mainimport "fmt"func main() …...
YOLOv5源码解读1.7-网络架构common.py
往期回顾:YOLOv5源码解读1.0-目录_汉卿HanQ的博客-CSDN博客 学习了yolo.py网络模型后,今天学习common.py,common.py存放这YOLOv5网络搭建的通用模块,如果修改某一块,就要修改这个文件中对应的模块 目录 1.导入python包 2.加载自…...

关于前端框架vue2升级为vue3的相关说明
一些框架需要升级 当前(202306) Vue 的最新稳定版本是 v3.3.4。Vue 框架升级为最新的3.0版本,涉及的相关依赖变更有: 前提条件:已安装 16.0 或更高版本的Node.js(摘) 必须的变更:核…...
gdb调试时查看汇编代码
在gdb中查看汇编代码,可以使用display命令或x命令。 以下是一个示例程序,我们以它为例来演示如何在gdb中查看汇编代码。 #include <stdio.h> int main() { int a 10; int b 20; int c a b; printf("c %d\n", c); return 0;…...

小研究 - JVM GC 对 IMS HSS 延迟分析(二)
用户归属服务器(IMS HSS)是下一代通信网(NGN)核心网络 IP 多媒体子系统(IMS)中的主要用户数据库。IMS HSS 中存储用户的配置文件,可执行用户的身份验证和授权,并提供对呼叫控制服务器…...

eNSP 路由器启动时一直显示 # 号的解决办法
文章目录 1 问题截图2 解决办法2.1 办法一:排除防火墙原因导致 3 验证是否成功 1 问题截图 路由器命令行一直显示 # 号,如下图 2 解决办法 2.1 办法一:排除防火墙原因导致 排查是否因为系统防火墙原因导致。放行与 eNSP 和 virtualbox 相…...

Kotlin~Facade
概念 又称门面模式,为复杂系统提供简单交互接口。 角色介绍 Facade:外观类,供客户端调用,将请求委派给响应的子系统。SubSystem:子系统,独立的子设备或子类 UML 代码实现 class Light(val name: Strin…...

高频面试之3Zookeeper
高频面试之3Zookeeper 文章目录 高频面试之3Zookeeper3.1 常用命令3.2 选举机制3.3 Zookeeper符合法则中哪两个?3.4 Zookeeper脑裂3.5 Zookeeper用来干嘛了 3.1 常用命令 ls、get、create、delete、deleteall3.2 选举机制 半数机制(过半机制࿰…...
vue3 字体颜色设置的多种方式
在Vue 3中设置字体颜色可以通过多种方式实现,这取决于你是想在组件内部直接设置,还是在CSS/SCSS/LESS等样式文件中定义。以下是几种常见的方法: 1. 内联样式 你可以直接在模板中使用style绑定来设置字体颜色。 <template><div :s…...
ffmpeg(四):滤镜命令
FFmpeg 的滤镜命令是用于音视频处理中的强大工具,可以完成剪裁、缩放、加水印、调色、合成、旋转、模糊、叠加字幕等复杂的操作。其核心语法格式一般如下: ffmpeg -i input.mp4 -vf "滤镜参数" output.mp4或者带音频滤镜: ffmpeg…...
Neo4j 集群管理:原理、技术与最佳实践深度解析
Neo4j 的集群技术是其企业级高可用性、可扩展性和容错能力的核心。通过深入分析官方文档,本文将系统阐述其集群管理的核心原理、关键技术、实用技巧和行业最佳实践。 Neo4j 的 Causal Clustering 架构提供了一个强大而灵活的基石,用于构建高可用、可扩展且一致的图数据库服务…...

NFT模式:数字资产确权与链游经济系统构建
NFT模式:数字资产确权与链游经济系统构建 ——从技术架构到可持续生态的范式革命 一、确权技术革新:构建可信数字资产基石 1. 区块链底层架构的进化 跨链互操作协议:基于LayerZero协议实现以太坊、Solana等公链资产互通,通过零知…...

dify打造数据可视化图表
一、概述 在日常工作和学习中,我们经常需要和数据打交道。无论是分析报告、项目展示,还是简单的数据洞察,一个清晰直观的图表,往往能胜过千言万语。 一款能让数据可视化变得超级简单的 MCP Server,由蚂蚁集团 AntV 团队…...

Spring Cloud Gateway 中自定义验证码接口返回 404 的排查与解决
Spring Cloud Gateway 中自定义验证码接口返回 404 的排查与解决 问题背景 在一个基于 Spring Cloud Gateway WebFlux 构建的微服务项目中,新增了一个本地验证码接口 /code,使用函数式路由(RouterFunction)和 Hutool 的 Circle…...

【7色560页】职场可视化逻辑图高级数据分析PPT模版
7种色调职场工作汇报PPT,橙蓝、黑红、红蓝、蓝橙灰、浅蓝、浅绿、深蓝七种色调模版 【7色560页】职场可视化逻辑图高级数据分析PPT模版:职场可视化逻辑图分析PPT模版https://pan.quark.cn/s/78aeabbd92d1...

AI病理诊断七剑下天山,医疗未来触手可及
一、病理诊断困局:刀尖上的医学艺术 1.1 金标准背后的隐痛 病理诊断被誉为"诊断的诊断",医生需通过显微镜观察组织切片,在细胞迷宫中捕捉癌变信号。某省病理质控报告显示,基层医院误诊率达12%-15%,专家会诊…...

云原生安全实战:API网关Kong的鉴权与限流详解
🔥「炎码工坊」技术弹药已装填! 点击关注 → 解锁工业级干货【工具实测|项目避坑|源码燃烧指南】 一、基础概念 1. API网关(API Gateway) API网关是微服务架构中的核心组件,负责统一管理所有API的流量入口。它像一座…...