手写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 ,所以跑的很慢 现象&#…...

IDEA运行Tomcat出现乱码问题解决汇总
最近正值期末周,有很多同学在写期末Java web作业时,运行tomcat出现乱码问题,经过多次解决与研究,我做了如下整理: 原因: IDEA本身编码与tomcat的编码与Windows编码不同导致,Windows 系统控制台…...
基于大模型的 UI 自动化系统
基于大模型的 UI 自动化系统 下面是一个完整的 Python 系统,利用大模型实现智能 UI 自动化,结合计算机视觉和自然语言处理技术,实现"看屏操作"的能力。 系统架构设计 #mermaid-svg-2gn2GRvh5WCP2ktF {font-family:"trebuchet ms",verdana,arial,sans-…...

2025年能源电力系统与流体力学国际会议 (EPSFD 2025)
2025年能源电力系统与流体力学国际会议(EPSFD 2025)将于本年度在美丽的杭州盛大召开。作为全球能源、电力系统以及流体力学领域的顶级盛会,EPSFD 2025旨在为来自世界各地的科学家、工程师和研究人员提供一个展示最新研究成果、分享实践经验及…...

定时器任务——若依源码分析
分析util包下面的工具类schedule utils: ScheduleUtils 是若依中用于与 Quartz 框架交互的工具类,封装了定时任务的 创建、更新、暂停、删除等核心逻辑。 createScheduleJob createScheduleJob 用于将任务注册到 Quartz,先构建任务的 JobD…...
【ROS】Nav2源码之nav2_behavior_tree-行为树节点列表
1、行为树节点分类 在 Nav2(Navigation2)的行为树框架中,行为树节点插件按照功能分为 Action(动作节点)、Condition(条件节点)、Control(控制节点) 和 Decorator(装饰节点) 四类。 1.1 动作节点 Action 执行具体的机器人操作或任务,直接与硬件、传感器或外部系统…...

江苏艾立泰跨国资源接力:废料变黄金的绿色供应链革命
在华东塑料包装行业面临限塑令深度调整的背景下,江苏艾立泰以一场跨国资源接力的创新实践,重新定义了绿色供应链的边界。 跨国回收网络:废料变黄金的全球棋局 艾立泰在欧洲、东南亚建立再生塑料回收点,将海外废弃包装箱通过标准…...

ServerTrust 并非唯一
NSURLAuthenticationMethodServerTrust 只是 authenticationMethod 的冰山一角 要理解 NSURLAuthenticationMethodServerTrust, 首先要明白它只是 authenticationMethod 的选项之一, 并非唯一 1 先厘清概念 点说明authenticationMethodURLAuthenticationChallenge.protectionS…...
Swagger和OpenApi的前世今生
Swagger与OpenAPI的关系演进是API标准化进程中的重要篇章,二者共同塑造了现代RESTful API的开发范式。 本期就扒一扒其技术演进的关键节点与核心逻辑: 🔄 一、起源与初创期:Swagger的诞生(2010-2014) 核心…...

OPenCV CUDA模块图像处理-----对图像执行 均值漂移滤波(Mean Shift Filtering)函数meanShiftFiltering()
操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 在 GPU 上对图像执行 均值漂移滤波(Mean Shift Filtering),用于图像分割或平滑处理。 该函数将输入图像中的…...
基于matlab策略迭代和值迭代法的动态规划
经典的基于策略迭代和值迭代法的动态规划matlab代码,实现机器人的最优运输 Dynamic-Programming-master/Environment.pdf , 104724 Dynamic-Programming-master/README.md , 506 Dynamic-Programming-master/generalizedPolicyIteration.m , 1970 Dynamic-Programm…...