手写Mybatis框架源码(简写)
pom文件:
springboot版本:2.6.5
jdk:8

<?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>org.example</groupId><artifactId>mybatis-boot</artifactId><version>1.0-SNAPSHOT</version><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.6.5</version></parent><properties><maven.compiler.source>8</maven.compiler.source><maven.compiler.target>8</maven.compiler.target><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding></properties><dependencies><!--web依赖--><dependency><!----><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!--测试--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId></dependency><!--测试--><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version><scope>test</scope></dependency><!--lombok依赖--><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.24</version></dependency><!--fastjson--><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.83</version></dependency><!--MySQL驱动--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.28</version></dependency><!--Dom4j依赖,比较流行的解析XML工具--><dependency><groupId>dom4j</groupId><artifactId>dom4j</artifactId><version>1.6.1</version></dependency><!--XPath(XML Path Language)的解析和查询库--><!--使用XPath表达式来查询和操作XML文档中的节点,从而实现对XML数据的处理和分析--><dependency><groupId>jaxen</groupId><artifactId>jaxen</artifactId><version>1.2.0</version></dependency><!--数据库连接池--><dependency><groupId>com.mchange</groupId><artifactId>c3p0</artifactId><version>0.9.5.5</version></dependency><!--在引入import注解的时候需要--><dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.9.7</version> <!-- 确保使用兼容的版本 --></dependency><dependency><groupId>org.aspectj</groupId><artifactId>aspectjrt</artifactId><version>1.9.7</version> <!-- 确保使用兼容的版本 --></dependency><!--reflections--><dependency><groupId>org.reflections</groupId><artifactId>reflections</artifactId><version>0.9.12</version> <!-- 确保使用兼容的版本 --></dependency></dependencies></project>
- mybatis执行原理(自己理解的)通过mapper注解或者是mapperscan注解去读取相应的mapper接口,通过这些接口文件的类对象去实现动态代理,通过动态代理实现了一个动态对象,将这个动态对象加入到bean对象当中。在启动的时候顺便将mapper的xml的各种数据进行一个保存,通过这些数据可以拿到操作sql的sql语句和入参类型和返回类型。
代码的实现:
- 启动类:
package org.example;import org.example.anno.MapperScan; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication @MapperScan(value = "org.example.mapper") //自己实现的Mapper注解 public class MybatisApplication {public static void main(String[] args) {SpringApplication.run(MybatisApplication.class,args);} }
2、MapperScan注解:
package org.example.anno;import org.example.handler.RegisterBeanMapperHandler;
import org.springframework.context.annotation.Import;import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;@Target(ElementType.TYPE) //注解的位置
@Retention(RetentionPolicy.RUNTIME) //运行时
@Import(RegisterBeanMapperHandler.class) //注解的注册器
public @interface MapperScan {String value() default "";
}
3、MapperScan的注册器:
package org.example.handler;import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.dom4j.DocumentException;
import org.example.anno.MapperScan;
import org.example.config.Configurations;
import org.example.dto.SqlData;
import org.example.executor.Executor;
import org.example.executor.impl.ExecutorImpl;
import org.example.session.Session;
import org.example.session.SessionInit;
import org.reflections.Reflections;
import org.reflections.scanners.SubTypesScanner;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.type.AnnotationMetadata;import java.beans.PropertyVetoException;
import java.lang.reflect.*;
import java.util.*;/*** 实现了bean的注册器,同时还实现了session接口,这个接口是自己实现的*/
@Slf4j
public class RegisterBeanMapperHandler implements ImportBeanDefinitionRegistrar, Session {private Configurations configurations; //xml的数据记录/*** * @param importingClassMetadata 添加了import注解的处理器对象* @param registry 注册器*/@SneakyThrows //lombok的异常处理@Overridepublic void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {//判断是否含有MapperScan注解if (!importingClassMetadata.isAnnotated(MapperScan.class.getName())) {return;}//获取mapperscan注解的属性Map<String, Object> annotationAttributes = importingClassMetadata.getAnnotationAttributes(MapperScan.class.getName());//获取这个mapper包的值String value = (String) annotationAttributes.get("value");//处理mapper.xml和数据库configurations = SessionInit.init();log.info("value: {}",value);//生成mapper接口的动态代理Map<String, Object> map = readMapperPackageData(value);if (registry instanceof DefaultListableBeanFactory){DefaultListableBeanFactory factory = (DefaultListableBeanFactory) registry;for (Map.Entry<String, Object> entry : map.entrySet()) {//将mapper生成的动态代理添加到bean容器当中,通过名字添加factory.registerSingleton(entry.getKey(),entry.getValue());}}}/*** * @param path 包名* @return* @throws ClassNotFoundException* @throws PropertyVetoException* @throws DocumentException*/public Map<String,Object> readMapperPackageData(String path) throws ClassNotFoundException, PropertyVetoException, DocumentException {Map<String,Object> map = new HashMap<>();//reflections的坑:是否excludeObjectClass排除这个包下的,默认为true。Reflections reflections = new Reflections(path,new SubTypesScanner(false));//如果默认为true,就会报SubType为null,就是说找不到Object相应的数据Set<Class<?>> allMapper = reflections.getSubTypesOf(Object.class);for (Class<?> aClass : allMapper) {//获取动态代理对象map.put(aClass.getSimpleName(),getMapper(aClass));}return map;}@Overridepublic <E> List<E> selectList(SqlData sqlData, Object... params) throws Exception {Executor executor = new ExecutorImpl();List<Object> query = executor.query(configurations, sqlData, params);return (List<E>) query;}@Overridepublic <E> E select(SqlData sqlData, Object... params) throws Exception {List<Object> objects = selectList(sqlData, params);if (objects == null || objects.size() ==0){return null;}if (objects.size()>1){throw new RuntimeException("查到不止一个");}return (E) objects.get(0);}@Overridepublic <E> E insert(SqlData sqlData, Object... params) throws Exception {Executor executor = new ExecutorImpl();List<Object> query = executor.query(configurations, sqlData, params);return (E) query.get(0);}@Overridepublic <E> E update(SqlData sqlData, Object... params) throws Exception {Executor executor = new ExecutorImpl();List<Object> query = executor.query(configurations, sqlData, params);return (E) query.get(0);}@Overridepublic <E> E delete(SqlData sqlData, Object... params) throws Exception {Executor executor = new ExecutorImpl();List<Object> query = executor.query(configurations, sqlData, params);return (E) query.get(0);}/*** * @param mapperType 要生成动态代理的类对象* @return* @param <T>* @throws PropertyVetoException* @throws DocumentException*/@Overridepublic <T> T getMapper(Class<?> mapperType) throws PropertyVetoException, DocumentException {//生成代理,通过代理处理你想要的结果Object instance =Proxy.newProxyInstance(mapperType.getClassLoader(), new Class[]{mapperType}, new InvocationHandler() {/*** method是动态代理对象的某个方法,args是这个方法的参数*/@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {//获得method的名字和类,拼接之后得到sql的数据,拿到sql的数据去执行相应的逻辑String methodName = method.getName();String className = method.getDeclaringClass().getName();//返回类型Type genericReturnType = method.getGenericReturnType();//通过这个去configurations拿值String key = className+"."+methodName;SqlData sqlData = configurations.getMap().get(key);//相应方法的sql数据String sqlType = sqlData.getType();if ("insert".equals(sqlType)){return insert(sqlData,args);}else if ("update".equals(sqlType)){return update(sqlData,args);} else if ("delete".equals(sqlType)) {return delete(sqlData,args);}//是否是参数化类型if (genericReturnType instanceof ParameterizedType){return selectList(sqlData,args);}else{return select(sqlData,args);}}});//返回动态代理对象return (T) instance;}
}
4、configurations:
package org.example.config;import lombok.Data;
import org.example.dto.SqlData;
import org.springframework.stereotype.Component;import javax.sql.DataSource;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;@Component
@Data
public class Configurations {private DataSource dataSource;Map<String, SqlData> map = new ConcurrentHashMap<>();
}
5、session:
package org.example.session;import org.dom4j.DocumentException;
import org.example.dto.SqlData;import java.beans.PropertyVetoException;
import java.util.List;public interface Session {<E>List<E> selectList(SqlData sqlData,Object ...params) throws Exception;<E> E select(SqlData sqlData,Object ...params) throws Exception;<E> E insert(SqlData sqlData,Object ...params) throws Exception;<E> E update(SqlData sqlData,Object ...params) throws Exception;<E> E delete(SqlData sqlData,Object ...params) throws Exception;<T> T getMapper(Class<?> mapperType) throws PropertyVetoException, DocumentException;
}
6、SessionInit:
package org.example.session;import lombok.Data;
import org.dom4j.DocumentException;
import org.example.config.Configurations;
import org.example.service.DatasourceXml;
import org.example.service.XmlBuilderService;
import org.springframework.stereotype.Component;import javax.annotation.PostConstruct;
import java.beans.PropertyVetoException;@Data
public class SessionInit {public static Configurations init() throws DocumentException, PropertyVetoException {Configurations configuration = new Configurations();//解析xml mapperXmlBuilderService xmlBuilderService = new XmlBuilderService(configuration);xmlBuilderService.parse();//数据库配置DatasourceXml datasourceXml = new DatasourceXml(configuration);datasourceXml.parse();//配置完之后,开始容器的创建,将所有的mapper进行封装,生成代理//通过返回bean对象将代理对象都交给bean容器管理return configuration;}
}
7、XmlBuilderMapper:
package org.example.service;import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.example.config.Configurations;
import org.example.dto.SqlData;import javax.annotation.PostConstruct;
import java.io.File;
import java.util.List;public class XmlBuilderService {private Configurations configuration;public XmlBuilderService(Configurations configuration) {this.configuration = configuration;}/*** 我在这里把地址写死了,当然可以在配置文件当中设置* @throws DocumentException*/public void parse() throws DocumentException {File folder = new File("src/main/resources/mapper");File[] files = folder.listFiles((dir,name)->{return name.endsWith(".xml");});for (File file : files) {SAXReader saxReader = new SAXReader();Document read = saxReader.read(file);Element readElements = read.getRootElement();//主标签上的属性String namespace = readElements.attributeValue("namespace");//主标签下的所有标签List<Element> elements = readElements.elements();//按照对应的namespace去找这个mapper对应的方法for (Element element : elements) {String name = element.getName();String id = element.attributeValue("id");String resultType = element.attributeValue("resultType");String parameterType = element.attributeValue("parameterType");String textTrim = element.getTextTrim();//解析为相应的数据,保存到configurations当中SqlData sqlData = new SqlData();sqlData.setId(id);sqlData.setSql(textTrim);sqlData.setParameterType(parameterType);sqlData.setResultType(resultType);sqlData.setType(name);String key = namespace+"."+id;System.out.println(key);configuration.getMap().put(namespace+"."+id,sqlData);}}}
}
<!--resource mapper包下的一个xml-->
<?xml version="1.0" encoding="UTF-8" ?><mapper namespace="org.example.mapper.OrderMapper"><select id="getList" resultType="org.example.entity.Order">select*from orders</select><update id ="update" resultType="java.lang.Integer" parameterType="org.example.entity.Order">update ordersset orders = #{orders},date=#{date}where id = #{id}</update><delete id="delete" resultType="java.lang.Integer" parameterType="org.example.entity.Order">delete from orderswhere id = #{id}</delete><insert id="insert" resultType="java.lang.Integer" parameterType="org.example.entity.Order">insert into orders values (#{id},#{orders},#{date})</insert>
</mapper>
8、DatasourceXmlBuilder:我在这里写死了,当然可以通过解析或者配置yml文件去读取
package org.example.service;import com.mchange.v2.c3p0.ComboPooledDataSource;
import org.example.config.Configurations;import java.beans.PropertyVetoException;public class DatasourceXml {private Configurations configuration;public DatasourceXml(Configurations configuration) {this.configuration = configuration;}public void parse() throws PropertyVetoException {ComboPooledDataSource dataSource= new ComboPooledDataSource();dataSource.setDriverClass("com.mysql.cj.jdbc.Driver");dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/ds0");dataSource.setUser("root");dataSource.setPassword("root");configuration.setDataSource(dataSource);}
}
SqlData:
package org.example.dto;import lombok.Data;@Data
public class SqlData {//方法名private String id;//返回类型private String resultType;//参数类型private String parameterType;//sql语句private String sql;//sql类型,select、update等等private String type;
}
BoundSql:
package org.example.dto;import lombok.Data;import java.util.ArrayList;
import java.util.List;@Data
public class BoundSql {//sql语句private String sql;//解析出来的sql当中的参数private List<String> paramsList =new ArrayList<>();
}
ExectuorImpl: 这段代码就不加注释了,自己理解了就好理解整个过程。
package org.example.executor.impl;import com.sun.deploy.ui.AboutDialog;
import org.example.config.Configurations;
import org.example.dto.BoundSql;
import org.example.dto.SqlData;
import org.example.executor.Executor;import javax.print.DocFlavor;
import javax.sql.DataSource;
import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.sql.*;
import java.util.*;public class ExecutorImpl implements Executor {@Overridepublic <T> List<T> query(Configurations configurations, SqlData sqlData, Object... args) throws SQLException, ClassNotFoundException, NoSuchFieldException, IllegalAccessException, InstantiationException, IntrospectionException, InvocationTargetException {DataSource dataSource = configurations.getDataSource();Connection connection = dataSource.getConnection();BoundSql boundSql = handleSql(sqlData.getSql());//String parameterType = sqlData.getParameterType();String sql = boundSql.getSql();List<String> paramsList = boundSql.getParamsList();PreparedStatement preparedStatement = connection.prepareStatement(sql);for (int i = 0; i < paramsList.size(); i++) {//参数替换,通过Method方法获取某个对象中某个对应的值String param = paramLists.get(i);Object arg = args[0];Class<?> type = getType(parameterType);//获取字段的对象,通过字段对象去匹配赋值Field declaredField = type.getDeclaredField(param);declaredField.setAccessible(true);Object filedValue = declaredField.get(arg);preparedStatement.setObject(i + 1, filedValue);}ResultSet resultSet;if ("select".equals(sqlData.getType())) {resultSet = preparedStatement.executeQuery();} else {int i = preparedStatement.executeUpdate();List<Integer> list = new ArrayList<>();list.add(i);return (List<T>) list;}if (resultSet == null){return null;}List<Object> resultList = new ArrayList<>(resultSet.getRow());String resultType = sqlData.getResultType();while (resultSet.next()){ResultSetMetaData metaData = resultSet.getMetaData();//获取列数int columnCount = metaData.getColumnCount();//创建一个返回类型的类对象Class<?> returnType = getType(resultType);//通过类对象创建一个返回对象Object instance = returnType.newInstance();for (int i = 1; i <= columnCount; i++) {//获取列的名字String columnName = metaData.getColumnName(i);System.out.println(columnName);//通过列的名字取值,并将列返回Object result = resultSet.getObject(columnName);System.out.println(result);//将列名与返回的类对象进行匹配PropertyDescriptor propertyDescriptor = new PropertyDescriptor(columnName,returnType);//得到一个写入方法Method writeMethod = propertyDescriptor.getWriteMethod();//将值写入到这个对象当中writeMethod.invoke(instance,result);}resultList.add(instance);}return (List<T>) resultList;}private Map<Integer,Integer> mapIndex = new LinkedHashMap<>();private List<String> paramLists = new ArrayList<>();private int fromIndex = 0;private BoundSql handleSql(String sql){submitSql(sql);for (Map.Entry<Integer, Integer> entry : mapIndex.entrySet()) {Integer begin = entry.getKey();Integer end = entry.getValue();String substring = sql.substring(begin + 2, end);paramLists.add(substring);}BoundSql boundSql = new BoundSql();for (String paramList : paramLists) {sql = sql.replace("#{" + paramList + "}", "?");boundSql.getParamsList().add(paramList);}boundSql.setSql(sql);//boundSql.setParamsList(paramLists);return boundSql;}private void submitSql(String sql) {int beginIndex = sql.indexOf("#{", fromIndex);if (beginIndex != -1){int endIndex = sql.indexOf("}", fromIndex + 1);if (endIndex != -1){fromIndex = endIndex+1;mapIndex.put(beginIndex,endIndex);submitSql(sql);}}}private Class<?> getType(String type) throws ClassNotFoundException {if (null == type || type.equals("")){return null;}return Class.forName(type);}}
总结:
总得来说,通过Proxy生成代理对象,通过代理对象调用相应的方法,相应的方法从configurations拿到相应的方法需要执行的sql语句。通过这个sql语句去执行JDBC基础的语句,也就是通过Connections去执行语句。
代码地址:lr-cc/fff
相关文章:
手写Mybatis框架源码(简写)
pom文件: springboot版本:2.6.5 jdk:8 <?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&q…...
Flask返回中文Unicode编码(乱码)解决方案
大家好,我是爱编程的喵喵。双985硕士毕业,现担任全栈工程师一职,热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。现为CSDN博客专家、人工智能领域优质创作者。喜欢通过博客创作的方式对所学的…...
最大值和最小值的差
最大值和最小值的差 C语言代码C 语言代码Java语言代码Python语言代码 💐The Begin💐点点关注,收藏不迷路💐 输出一个整数序列中最大的数和最小的数的差。 输入 第一行为M,表示整数个数,整数个数不会大于1…...
如何在 IntelliJ IDEA 中为 Spring Boot 应用实现热部署
文章目录 1. 引言2. 准备工作3. 添加必要的依赖4. 配置 IntelliJ IDEA4.1 启用自动编译4.2 开启热部署策略 5. 测试热部署6. 高级技巧7. 注意事项8. 总结 随着现代开发工具的进步,开发者们越来越重视提高生产力的特性。对于 Java 开发者来说,能够在不重启…...
探索 Java 中的 Bug 世界
在 Java 编程的旅程中,我们不可避免地会遇到各种 Bug。这些 Bug 可能会导致程序出现意外的行为、崩溃或者性能问题。了解 Java Bug 的类型、产生原因以及解决方法,对于提高我们的编程技能和开发出稳定可靠的应用程序至关重要。 一、Java Bug 的定义与分类…...
SQL面试题——百度SQL面试题 连续签到领金币
百度SQL面试题 连续签到领金币 今天的这个题目来自百度,而且这个题目很常见,是一个大家日常经常遇到的一个场景,几乎无处不在,就是签到送积分,只不过这里是签到领金币 有用户签到记录表,sign,记录用户当天是否完成签到,请计算出每个用户的每个月获得的金币数量; 签到…...
easyExcel单一下拉框和级联下拉框
文章目录: 单一下拉框级联下拉框 具体实现: 单一下拉框 public class BoolWriteHandler implements SheetWriteHandler {private List<String> dropDown;private List<Integer> indexList;public BoolWriteHandler(List<Integer> i…...
linux-安全-iptables防火墙基础笔记
目录 一、 iptables链结构 五链 二、 iptables表结构 四表 三、 匹配流程 四、 语法 五、 匹配 1. 通用匹配 2. 隐含匹配 3. 显示匹配 六、 SNAT 七、 DNAT 八、 规则备份及还原 1. 备份 2. 还原 这篇将讲解iptables防火墙的基础知识 一、 iptables链结构 规则…...
力扣刷题TOP101: 25.BM32合并二叉树
目录: 目的 思路 复杂度 记忆秘诀 python代码 目的: 已知两颗二叉树,将它们合并成一颗二叉树。合并规则是:都存在的结点,就将结点值加起来,否则空的位置就由另一个树的结点来代替。 思路 我们有两棵二…...
R的中文文本处理包--tmcn
文章目录 介绍tmcn 和 jieba 的关系函数:catUTF8toUTF8实例 介绍 tmcn 包是 R 语言中的一个用于处理和分析中文文本的包,特别适用于中文文本的分词、词频统计和文本挖掘等任务。以下是 tmcn 包的基本用法,包括安装、常用函数和示例。 一个用…...
差异基因富集分析(R语言——GOKEGGGSEA)
接着上次的内容,上篇内容给大家分享了基因表达量怎么做分组差异分析,从而获得差异基因集,想了解的可以去看一下,这篇主要给大家分享一下得到显著差异基因集后怎么做一下通路富集。 1.准备差异基因集 我就直接把上次分享的拿到这…...
scrapy对接rabbitmq的时候使用post请求
之前做分布式爬虫的时候,都是从push url来拿到爬虫消费的链接,这里提出一个问题,假如这个请求是post请求的呢,我观察了scrapy-redis的源码,其中spider.py的代码是这样写的 1.scrapy-redis源码分析 def make_request_from_data(self, data):"""Returns a Reques…...
vue+elementUI+transition实现鼠标滑过div展开内容,鼠标划出收起内容,加防抖功能
文章目录 一、场景二、实现代码1.子组件代码结构2.父组件 一、场景 这两天做项目,此产品提出需求 要求详情页的顶部区域要在鼠标划入后展开里面的内容,鼠标划出要收起部分内容,详情底部的内容高度要自适应,我这里运用了鼠标事件t…...
大模型语料库的构建过程 包括知识图谱构建 垂直知识图谱构建 输入到sql构建 输入到cypher构建 通过智能体管理数据生产组件
以下是大模型语料库的构建过程: 一、文档切分语料库构建 数据来源确定: 首先,需要确定语料库的数据来源。这些来源可以是多种多样的,包括但不限于: 网络资源:利用网络爬虫技术从各种网站(如新闻…...
阿里云ECS服务器域名解析
阿里云ECS服务器域名解析,以前添加两条A记录类型,主机记录分别为www和,这2条记录都解析到服务器IP地址。 1.进入阿里云域名控制台,找到域名 ->“解析设置”->“添加记录” 2.添加一条记录类型为A,主机记录为www,…...
牛客周赛71:A:JAVA
链接:登录—专业IT笔试面试备考平台_牛客网 来源:牛客网 题目描述 \hspace{15pt}对于给定的两个正整数 nnn 和 kkk ,是否能构造出 kkk 对不同的正整数 (x,y)(x,y)(x,y) ,使得 xynxynxyn 。 \hspace{15pt}我们认为两对正整数 (…...
查询产品所涉及的表有(product、product_admin_mapping)
文章目录 1、ProductController2、AdminCommonService3、ProductApiService4、ProductCommonService5、ProductSqlService1. 完整SQL分析可选部分(条件筛选): 2. 涉及的表3. 总结4. 功能概述 查询指定管理员下所有产品所涉及的表?…...
算法基础学习Day5(双指针、动态窗口)
文章目录 1.题目2.题目解答1.四数之和题目及题目解析算法学习代码提交 2.长度最小的子数组题目及题目解析滑动窗口的算法学习方法一:单向双指针(暴力解法)方法二:同向双指针(滑动窗口) 代码提交 1.题目 18. 四数之和 - 力扣(LeetCode&#x…...
docker 部署 mysql 9.0.1
docker 如何部署 mysql 9 ,请看下面步骤: 1. 先看 mysql 官网 先点进去 8 版本的 Reference Manual 。 选择 9.0 版本的。 点到这里来看, 这里有一些基础的安装步骤,可以看一下。 - Basic Steps for MySQL Server Deployment wit…...
关于小标join大表,操作不当会导致笛卡尔积,数据倾斜
以前总是说笛卡尔积,笛卡尔积,没碰到过,今天在跑流程调度时,就碰到笛卡尔积了,本来,就是查询几个编码的信息,然后由于使用的是with tmp as,没使用where in ,所以跑的很慢 现象&#…...
【Java学习笔记】Arrays类
Arrays 类 1. 导入包:import java.util.Arrays 2. 常用方法一览表 方法描述Arrays.toString()返回数组的字符串形式Arrays.sort()排序(自然排序和定制排序)Arrays.binarySearch()通过二分搜索法进行查找(前提:数组是…...
Day131 | 灵神 | 回溯算法 | 子集型 子集
Day131 | 灵神 | 回溯算法 | 子集型 子集 78.子集 78. 子集 - 力扣(LeetCode) 思路: 笔者写过很多次这道题了,不想写题解了,大家看灵神讲解吧 回溯算法套路①子集型回溯【基础算法精讲 14】_哔哩哔哩_bilibili 完…...
python/java环境配置
环境变量放一起 python: 1.首先下载Python Python下载地址:Download Python | Python.org downloads ---windows -- 64 2.安装Python 下面两个,然后自定义,全选 可以把前4个选上 3.环境配置 1)搜高级系统设置 2…...
Docker 运行 Kafka 带 SASL 认证教程
Docker 运行 Kafka 带 SASL 认证教程 Docker 运行 Kafka 带 SASL 认证教程一、说明二、环境准备三、编写 Docker Compose 和 jaas文件docker-compose.yml代码说明:server_jaas.conf 四、启动服务五、验证服务六、连接kafka服务七、总结 Docker 运行 Kafka 带 SASL 认…...
select、poll、epoll 与 Reactor 模式
在高并发网络编程领域,高效处理大量连接和 I/O 事件是系统性能的关键。select、poll、epoll 作为 I/O 多路复用技术的代表,以及基于它们实现的 Reactor 模式,为开发者提供了强大的工具。本文将深入探讨这些技术的底层原理、优缺点。 一、I…...
Spring AI与Spring Modulith核心技术解析
Spring AI核心架构解析 Spring AI(https://spring.io/projects/spring-ai)作为Spring生态中的AI集成框架,其核心设计理念是通过模块化架构降低AI应用的开发复杂度。与Python生态中的LangChain/LlamaIndex等工具类似,但特别为多语…...
Yolov8 目标检测蒸馏学习记录
yolov8系列模型蒸馏基本流程,代码下载:这里本人提交了一个demo:djdll/Yolov8_Distillation: Yolov8轻量化_蒸馏代码实现 在轻量化模型设计中,**知识蒸馏(Knowledge Distillation)**被广泛应用,作为提升模型…...
Golang——7、包与接口详解
包与接口详解 1、Golang包详解1.1、Golang中包的定义和介绍1.2、Golang包管理工具go mod1.3、Golang中自定义包1.4、Golang中使用第三包1.5、init函数 2、接口详解2.1、接口的定义2.2、空接口2.3、类型断言2.4、结构体值接收者和指针接收者实现接口的区别2.5、一个结构体实现多…...
LCTF液晶可调谐滤波器在多光谱相机捕捉无人机目标检测中的作用
中达瑞和自2005年成立以来,一直在光谱成像领域深度钻研和发展,始终致力于研发高性能、高可靠性的光谱成像相机,为科研院校提供更优的产品和服务。在《低空背景下无人机目标的光谱特征研究及目标检测应用》这篇论文中提到中达瑞和 LCTF 作为多…...
vue3 daterange正则踩坑
<el-form-item label"空置时间" prop"vacantTime"> <el-date-picker v-model"form.vacantTime" type"daterange" start-placeholder"开始日期" end-placeholder"结束日期" clearable :editable"fal…...
