手写mybatis

手写mybatis
mybatis仓库地址点击文字即可跳转

package com.mybatis.factory;import com.mybatis.mapper.ParameterMapping;
import com.mybatis.retention.Selcet;
import com.mybatis.token.GenericTokenParser;
import com.mybatis.token.ParameterMappingTokenHandler;
import com.mybatis.token.TypeHander;
import com.mybatis.type.*;
import com.mybatis.util.MapperUtil;
import java.lang.reflect.*;
import java.sql.*;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;public class MapperProxyFactory {private static Map<Class, TypeHander> typeHanderMap=new ConcurrentHashMap<>();//第一种请求方式static {typeHanderMap.put(String.class,new StringTypeHander());typeHanderMap.put(Integer.class,new IntegerTypeHander());try {Class.forName("come.mysql.cj.jdbc.Driver");} catch (ClassNotFoundException classNotFoundException) {classNotFoundException.printStackTrace();}}public static <T> T getMapper(Class<T> tClass){return(T) Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(), new Class[]{tClass}, new InvocationHandler() {@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {//处理sql//第一种sql链接方式Connection connection = MapperUtil.getConnection();//第二种//  Connection connection1 = DataSourceFactory.connection();Map<String, Object> map = MapperUtil.getStringObjectMap(method, args);ParameterMappingTokenHandler parameterMappingTokenHandler=new ParameterMappingTokenHandler();GenericTokenParser parser=new GenericTokenParser("#{","}",parameterMappingTokenHandler);List<ParameterMapping> parameterMappings = parameterMappingTokenHandler.getParameterMappings();PreparedStatement statement = connection.prepareStatement(MapperUtil.sql(method,parser));updateStatement(map, parameterMappings, statement);statement.execute();if (!method.getAnnotations()[0].equals(Selcet.class)){connection.close();return null;}Class resultType=null;resultType = MapperUtil.getResultType(method, resultType);ResultSet resultSet = statement.getResultSet();List<String> columList =MapperUtil. getColumList(resultSet);Map<String, Method> methodMap = MapperUtil.getStringMethodMap(resultType);Object result=null;List<Object> list=new ArrayList<>();Map<Integer,Object> handerMap=new ConcurrentHashMap<>();while (resultSet.next()){if (resultType!=null) {Object instance = resultType.newInstance();for (int i=0;i<columList.size();i++){selecteInstance(resultSet, columList, methodMap, instance, i);list.add(instance);handerMap.put(i,instance);}}}result = MapperUtil.getResult(method, list, handerMap);connection.close();return result;}});}private static void selecteInstance(ResultSet resultSet, List<String> columList, Map<String, Method> methodMap, Object instance, int i) throws IllegalAccessException, InvocationTargetException, SQLException {String column = columList.get(i);Method set = methodMap.get(column);Class<?> parameterType = set.getParameterTypes()[0];TypeHander typeHander = typeHanderMap.get(parameterType);set.invoke(instance,typeHander.getResult(resultSet,column));}private static void updateStatement(Map<String, Object> map, List<ParameterMapping> parameterMappings, PreparedStatement statement) throws SQLException {for (int i = 0; i< parameterMappings.size(); i++){String parameter= parameterMappings.get(i).getProperty();Object o = map.get(parameter);Class<?> aClass = o.getClass();typeHanderMap.get(aClass).setParameter(statement,i+1,o);}}
}
package com.mybatis.type;import com.mybatis.token.TypeHander;import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;public class IntegerTypeHander implements TypeHander<Integer> {@Overridepublic void setParameter(PreparedStatement statement, int i, Integer value) throws SQLException {statement.setInt(i,value);}@Overridepublic Integer getResult(ResultSet resultSet, String cloumn) throws SQLException {return resultSet.getInt(cloumn);}
}
package com.mybatis.token;public class GenericTokenParser {/*** 占位符开始标志*/private final String openToken;/*** 占位符结束标志*/private final String closeToken;/****/private final TokenHandler handler;public GenericTokenParser(String openToken, String closeToken, TokenHandler handler) {this.openToken = openToken;this.closeToken = closeToken;this.handler = handler;}/***这段代码主要处理{@code text}拥有多个符合以{@code openToken}开头,{@code closeToken}结尾的字符窜的情况** 同时还要处理拥有{@code openToken}{@code closeToken},但是使用了转义字符的情况。** @param text* @return*/public String parse(String text) {//非空判断if (text == null || text.isEmpty()) {return "";}// search open token//获取第一个{@code openToken}的位置int start = text.indexOf(openToken);//如果这个位置不存在 则直接返回原字符窜if (start == -1) {return text;}//生成原字符窜的数组char[] src = text.toCharArray();//字符窜拥有多个符合条件的{@code openToken}时,将会进行多轮分析,以确认每一轮的{@code openToken}在原字符窜的位置,而//offset就表示每一轮解析时,应该从原字符窜的哪个位置开始int offset = 0;//builder是拼接最后结果,进行输出的final StringBuilder builder = new StringBuilder();//expression的内容表示{@code openToken}{@code closeToken}之间的内容StringBuilder expression = null;//下面这个循环 就是循环处理多个{@code openToken}{@code closeToken}的情况while (start > -1) {if (start > 0 && src[start - 1] == '\\') {//寻找{@code openToken}的条件分支一:这一个条件判断 是处理出现了{@code openToken},但是这个{@code openToken}前面出现了转移字符// this open token is escaped. remove the backslash and continue.//这里表示既然遇到了转义字符 那么这个开始标识符不能当做开始标识符// 因此它不是需要替换的部分,所以就要将从本轮开启的位置 到{@code openToken}结束位置的字符都直接拼接到{@code builder}上builder.append(src, offset, start - offset - 1).append(openToken);//确认新一轮的开始位置offset = start + openToken.length();} else {//寻找{@code openToken}的条件分支二:下面的条件判断表示 出现了{@code openToken} 且 这个{@code openToken}前面没有转移字符的情况===// found open token. let's search close token.//重置复用expressionif (expression == null) {expression = new StringBuilder();} else {expression.setLength(0);}//这里表示如果有转义字符 则拼接转义的开始字符到真正的开始字符之间的部分builder.append(src, offset, start - offset);//{@code openToken}找到了,接下来来需要找{@code closeToken},其实{@code closeToken}的状况和{@code openToken}//一样的情况offset = start + openToken.length();int end = text.indexOf(closeToken, offset);//遍历循环一直找{@code closeToken}的位置while (end > -1) {if (end > offset && src[end - 1] == '\\') {//寻找{@code closeToken}的分支条件一:如果找到的{@code closeToken}是拥有转义字符的,则继续寻找,但是expression需要拼接本轮解析开始//位置到{@code openToken}间的字符,因为这个也属于{@code openToken}{@code closeToken}间的内容,然后进行下一轮// this close token is escaped. remove the backslash and continue.expression.append(src, offset, end - offset - 1).append(closeToken);offset = end + closeToken.length();end = text.indexOf(closeToken, offset);} else {//寻找{@code closeToken}的分支条件二:这里表示找到了符合条件的{@code closeToken},那么将内容拼接到{@code expression}里expression.append(src, offset, end - offset);break;}}if (end == -1) {//综合评定 条件分支一:{@code closeToken}位置没有找到,那么结束了,直接拼接// close token was not found.builder.append(src, start, src.length - start);offset = src.length;} else {//综合评定 条件分支二:{@code closeToken}位置也找到了,那么说明expression里也存放好了{@code openToken}{@code closeToken}//内容,这时候用handler去处理。builder.append(handler.handleToken(expression.toString()));offset = end + closeToken.length();}}//这里表示 从offset位置 从新获取start的位置,很显然如果为0,start还是不变start = text.indexOf(openToken, offset);}if (offset < src.length) {builder.append(src, offset, src.length - offset);}return builder.toString();}
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

#vu3# element plus表格的序号字段

在表格中添加序号字段&#xff0c;可以使用以下几种方式来实现 1. 利用索引 在<el-table>组件的<el-table-column>中使用插槽来显示序号。示例&#xff1a; <el-table :data"tableData"><el-table-column label"序号" type"i…

Jmeter接口自动化测试 —— Jmeter断言之Json断言

json断言可以让我们很快的定位到响应数据中的某一字段&#xff0c;当然前提是响应数据是json格式的&#xff0c;所以如果响应数据为json格式的话&#xff0c;使用json断言还是相当方便的。 还是以之前的接口举例 Url: https://data.cma.cn/weatherGis/web/weather/weatherFcst…

linux中的mtime,ctime,atime

目录 结论 文件 touch新文件 调整文件内容 echo直接修改 vi修改 修改文件属性 调整归属 调整权限 读取文件 目录 增加文件 调整目录下文件属性 访问目录下文件 删除文件 结论 mtime&#xff1a;文件内容的修改时间&#xff08;不含权限、属组修改&#xff09; …

springboot在线文档的集成方式

为了使用Swagger 3&#xff0c;您需要进行以下步骤来将其集成到您的项目中&#xff1a; 添加Swagger依赖项&#xff1a;在您的项目的构建文件中&#xff0c;例如pom.xml&#xff08;如果您的项目是基于Maven&#xff09;&#xff0c;添加Swagger库的依赖项。您可以在Maven中添…

实习记录——第十三天

明天要回家了&#xff0c;今天啥也不想干&#xff0c;看了一集小迪的课&#xff0c;日报写的堂而皇之&#xff0c;我都害怕&#xff0c;中午忘记吃饭了&#xff0c;吃了一点儿饼干&#xff0c;结果下班回校的时候&#xff0c;感觉手有些颤抖&#xff0c;我在网上看好了吃的地方…

mobi, azw, azw3, epub格式有什么区别

mobi, azw, azw3, epub格式有什么区别 对复杂排版的支持上是azw3好。 对使用方便来说是mobi好&#xff0c;因为可以邮件推送。 刚接触Kindle的小伙伴经常会被mobi、azw、azw3、epub等常见的几个格式搞的很凌乱&#xff0c;它们都有哪些区别呢&#xff1f;又各有什么优缺点呢&am…

1 引论

1 引论 操作系统&#xff08;OS&#xff09; -管理计算机系统资源、控制程序执行、改善人机界面、提供各种服务&#xff0c;并合理组织计算机工作流程和为用户方便有效地使用计算机&#xff0c;提供良好运行环境的一种系统软件 操作系统的目标 方便性 2. 有效性 3. 可扩充性 4…

C++泛编程(4)

类模板高级&#xff08;1&#xff09; 1.类模板具体化部分具体化完全具体化 2.类模板与继承 1.类模板具体化 有了函数模板具体化的基础&#xff0c;学习类模板的具体化很简单。类模板具体化有两种方式&#xff0c;分别为部分具体化和完全具体化。假如有类模板&#xff1a; te…

户用光伏电站设计优化方案:为行业打造示范标杆

不可再生能源的日益消耗促使了大家对新能源的使用和推广&#xff0c;光伏发电已经成为国家和企业大力推崇的技术。其中&#xff0c;户用光伏发电是重要组成部分&#xff0c;有非常大的市场发展空间。然而&#xff0c;如何优化设计&#xff0c;提高效率&#xff0c;降低成本&…

蓝桥杯备战(AcWing算法基础课)-高精度-减-高精度

目录 前言 1 题目描述 2 分析 2.1 第一步 2.2 第二步 3 代码 前言 详细的代码里面有自己的理解注释 1 题目描述 给定两个正整数&#xff08;不含前导 00&#xff09;&#xff0c;计算它们的差&#xff0c;计算结果可能为负数。 输入格式 共两行&#xff0c;每行包含一…

【Iceberg学习二】Branch和Tag在Iceberg中的应用

Iceberg 表元数据保持一个快照日志&#xff0c;记录了对表所做的更改。快照在 Iceberg 中至关重要&#xff0c;因为它们是读者隔离和时间旅行查询的基础。为了控制元数据大小和存储成本&#xff0c;Iceberg 提供了快照生命周期管理程序&#xff0c;如 expire_snapshots&#xf…

函数调用栈是什么

今天在力扣leetbook上看《图解算法数据结构》中的空间复杂度这一小节&#xff0c;看到如下这句话&#xff1a; “程序调用函数是基于栈实现的&#xff0c;函数在调用期间&#xff0c;占用常量大小的栈帧空间&#xff0c;直至返回后释放。” 这句话的意思是&#xff0c;在程序中…

2.3作业

作业要求&#xff1a; 程序代码&#xff1a; #include<stdlib.h> #include<string.h> #include<stdio.h> typedef struct node //定义链表节点结构体&#xff1a;数据域、指针域 {int data;struct node *next; }*linklist;linklist create_node()//创建新节…

C++类和对象入门(三)

顾得泉&#xff1a;个人主页 个人专栏&#xff1a;《Linux操作系统》 《C从入门到精通》 《LeedCode刷题》 键盘敲烂&#xff0c;年薪百万&#xff01; 前言 在c中&#xff0c;类型分为两类&#xff0c;一类是内置类型&#xff0c;另一类是自定义类型。 1.内置类型&#xf…

Linux内存管理:(十二)Linux 5.0内核新增的反碎片优化

文章说明&#xff1a; Linux内核版本&#xff1a;5.0 架构&#xff1a;ARM64 参考资料及图片来源&#xff1a;《奔跑吧Linux内核》 Linux 5.0内核源码注释仓库地址&#xff1a; zhangzihengya/LinuxSourceCode_v5.0_study (github.com) 外碎片化发生时&#xff0c;页面分配…

Python基础知识:Python流程控制语句

流程控制就是控制程序如何执行的方法&#xff0c;适用于任何一门编程语言&#xff0c;其作用在于&#xff0c;可以根据用户的需求决定程序执行的顺序。计算机在运行程序时&#xff0c;有3种执行方法&#xff0c;第一种是顺序执行&#xff0c;自上而下顺序执行所有的语句&#x…

分享63个节日PPT,总有一款适合您

分享63个节日PPT&#xff0c;总有一款适合您 63个节日PPT下载链接&#xff1a;https://pan.baidu.com/s/1kZeiN06KbevtSCs5vXm6oA?pwd6666 提取码&#xff1a;6666 Python采集代码下载链接&#xff1a;采集代码.zip - 蓝奏云 学习知识费力气&#xff0c;收集整理更不易…

【代码随想录-哈希表】两个数组的交集

💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学习,不断总结,共同进步,活到老学到老导航 檀越剑指大厂系列:全面总结 jav…

MySQL 小技巧:使用 xtrabackup 2.4 实现 完全备份及还原

演示&#xff1a;使用 xtrabackup 2.4 实现 完全备份及还原 本案例基于 CentOS 7 的 Mariadb5.5 实现&#xff0c;也支持 MySQL5.5 和 MySQL5.7 1) 安装 xtrabackup 包 // 先安装 Mariadb5.5 和 xtrabackup 包 [rootcentos7 ~] yum install mariadb-server -y [rootcentos7 ~]…

802.11 MAC帧介绍

控制帧 RTS&#xff08;Request To Send&#xff09;&#xff1a;用于申请无线媒介的使用时间CTS&#xff08;Clear To Send&#xff09;&#xff1a;用于回复RTS帧ACK&#xff1a;对MAC帧的肯定确认PS-POLL&#xff1a;STA用于从AP中获取因省电模式而缓存的数据&#xff0c;只…