当前位置: 首页 > news >正文

手写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>
  1. mybatis执行原理(自己理解的)通过mapper注解或者是mapperscan注解去读取相应的mapper接口,通过这些接口文件的类对象去实现动态代理,通过动态代理实现了一个动态对象,将这个动态对象加入到bean对象当中。在启动的时候顺便将mapper的xml的各种数据进行一个保存,通过这些数据可以拿到操作sql的sql语句和入参类型和返回类型。

代码的实现:

  1. 启动类:
    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文件&#xff1a; springboot版本&#xff1a;2.6.5 jdk&#xff1a;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语言代码 &#x1f490;The Begin&#x1f490;点点关注&#xff0c;收藏不迷路&#x1f490; 输出一个整数序列中最大的数和最小的数的差。 输入 第一行为M&#xff0c;表示整数个数&#xff0c;整数个数不会大于1…...

如何在 IntelliJ IDEA 中为 Spring Boot 应用实现热部署

文章目录 1. 引言2. 准备工作3. 添加必要的依赖4. 配置 IntelliJ IDEA4.1 启用自动编译4.2 开启热部署策略 5. 测试热部署6. 高级技巧7. 注意事项8. 总结 随着现代开发工具的进步&#xff0c;开发者们越来越重视提高生产力的特性。对于 Java 开发者来说&#xff0c;能够在不重启…...

探索 Java 中的 Bug 世界

在 Java 编程的旅程中&#xff0c;我们不可避免地会遇到各种 Bug。这些 Bug 可能会导致程序出现意外的行为、崩溃或者性能问题。了解 Java Bug 的类型、产生原因以及解决方法&#xff0c;对于提高我们的编程技能和开发出稳定可靠的应用程序至关重要。 一、Java Bug 的定义与分类…...

SQL面试题——百度SQL面试题 连续签到领金币

百度SQL面试题 连续签到领金币 今天的这个题目来自百度,而且这个题目很常见,是一个大家日常经常遇到的一个场景,几乎无处不在,就是签到送积分,只不过这里是签到领金币 有用户签到记录表,sign,记录用户当天是否完成签到,请计算出每个用户的每个月获得的金币数量; 签到…...

easyExcel单一下拉框和级联下拉框

文章目录&#xff1a; 单一下拉框级联下拉框 具体实现&#xff1a; 单一下拉框 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合并二叉树

目录&#xff1a; 目的 思路 复杂度 记忆秘诀 python代码 目的&#xff1a; 已知两颗二叉树&#xff0c;将它们合并成一颗二叉树。合并规则是&#xff1a;都存在的结点&#xff0c;就将结点值加起来&#xff0c;否则空的位置就由另一个树的结点来代替。 思路 我们有两棵二…...

R的中文文本处理包--tmcn

文章目录 介绍tmcn 和 jieba 的关系函数&#xff1a;catUTF8toUTF8实例 介绍 tmcn 包是 R 语言中的一个用于处理和分析中文文本的包&#xff0c;特别适用于中文文本的分词、词频统计和文本挖掘等任务。以下是 tmcn 包的基本用法&#xff0c;包括安装、常用函数和示例。 一个用…...

差异基因富集分析(R语言——GOKEGGGSEA)

接着上次的内容&#xff0c;上篇内容给大家分享了基因表达量怎么做分组差异分析&#xff0c;从而获得差异基因集&#xff0c;想了解的可以去看一下&#xff0c;这篇主要给大家分享一下得到显著差异基因集后怎么做一下通路富集。 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.父组件 一、场景 这两天做项目&#xff0c;此产品提出需求 要求详情页的顶部区域要在鼠标划入后展开里面的内容&#xff0c;鼠标划出要收起部分内容&#xff0c;详情底部的内容高度要自适应&#xff0c;我这里运用了鼠标事件t…...

大模型语料库的构建过程 包括知识图谱构建 垂直知识图谱构建 输入到sql构建 输入到cypher构建 通过智能体管理数据生产组件

以下是大模型语料库的构建过程&#xff1a; 一、文档切分语料库构建 数据来源确定&#xff1a; 首先&#xff0c;需要确定语料库的数据来源。这些来源可以是多种多样的&#xff0c;包括但不限于&#xff1a; 网络资源&#xff1a;利用网络爬虫技术从各种网站&#xff08;如新闻…...

阿里云ECS服务器域名解析

阿里云ECS服务器域名解析&#xff0c;以前添加两条A记录类型&#xff0c;主机记录分别为www和&#xff0c;这2条记录都解析到服务器IP地址。 1.进入阿里云域名控制台&#xff0c;找到域名 ->“解析设置”->“添加记录” 2.添加一条记录类型为A,主机记录为www&#xff0c…...

牛客周赛71:A:JAVA

链接&#xff1a;登录—专业IT笔试面试备考平台_牛客网 来源&#xff1a;牛客网 题目描述 \hspace{15pt}对于给定的两个正整数 nnn 和 kkk &#xff0c;是否能构造出 kkk 对不同的正整数 (x,y)(x,y)(x,y) &#xff0c;使得 xynxynxyn 。 \hspace{15pt}我们认为两对正整数 (…...

查询产品所涉及的表有(product、product_admin_mapping)

文章目录 1、ProductController2、AdminCommonService3、ProductApiService4、ProductCommonService5、ProductSqlService1. 完整SQL分析可选部分&#xff08;条件筛选&#xff09;&#xff1a; 2. 涉及的表3. 总结4. 功能概述 查询指定管理员下所有产品所涉及的表&#xff1f;…...

算法基础学习Day5(双指针、动态窗口)

文章目录 1.题目2.题目解答1.四数之和题目及题目解析算法学习代码提交 2.长度最小的子数组题目及题目解析滑动窗口的算法学习方法一&#xff1a;单向双指针(暴力解法)方法二&#xff1a;同向双指针(滑动窗口) 代码提交 1.题目 18. 四数之和 - 力扣&#xff08;LeetCode&#x…...

docker 部署 mysql 9.0.1

docker 如何部署 mysql 9 &#xff0c;请看下面步骤&#xff1a; 1. 先看 mysql 官网 先点进去 8 版本的 Reference Manual 。 选择 9.0 版本的。 点到这里来看&#xff0c; 这里有一些基础的安装步骤&#xff0c;可以看一下。 - Basic Steps for MySQL Server Deployment wit…...

关于小标join大表,操作不当会导致笛卡尔积,数据倾斜

以前总是说笛卡尔积&#xff0c;笛卡尔积&#xff0c;没碰到过&#xff0c;今天在跑流程调度时&#xff0c;就碰到笛卡尔积了&#xff0c;本来&#xff0c;就是查询几个编码的信息&#xff0c;然后由于使用的是with tmp as&#xff0c;没使用where in ,所以跑的很慢 现象&#…...

网络六边形受到攻击

大家读完觉得有帮助记得关注和点赞&#xff01;&#xff01;&#xff01; 抽象 现代智能交通系统 &#xff08;ITS&#xff09; 的一个关键要求是能够以安全、可靠和匿名的方式从互联车辆和移动设备收集地理参考数据。Nexagon 协议建立在 IETF 定位器/ID 分离协议 &#xff08;…...

label-studio的使用教程(导入本地路径)

文章目录 1. 准备环境2. 脚本启动2.1 Windows2.2 Linux 3. 安装label-studio机器学习后端3.1 pip安装(推荐)3.2 GitHub仓库安装 4. 后端配置4.1 yolo环境4.2 引入后端模型4.3 修改脚本4.4 启动后端 5. 标注工程5.1 创建工程5.2 配置图片路径5.3 配置工程类型标签5.4 配置模型5.…...

Qt Widget类解析与代码注释

#include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this); }Widget::~Widget() {delete ui; }//解释这串代码&#xff0c;写上注释 当然可以&#xff01;这段代码是 Qt …...

第 86 场周赛:矩阵中的幻方、钥匙和房间、将数组拆分成斐波那契序列、猜猜这个单词

Q1、[中等] 矩阵中的幻方 1、题目描述 3 x 3 的幻方是一个填充有 从 1 到 9 的不同数字的 3 x 3 矩阵&#xff0c;其中每行&#xff0c;每列以及两条对角线上的各数之和都相等。 给定一个由整数组成的row x col 的 grid&#xff0c;其中有多少个 3 3 的 “幻方” 子矩阵&am…...

rnn判断string中第一次出现a的下标

# coding:utf8 import torch import torch.nn as nn import numpy as np import random import json""" 基于pytorch的网络编写 实现一个RNN网络完成多分类任务 判断字符 a 第一次出现在字符串中的位置 """class TorchModel(nn.Module):def __in…...

iOS性能调优实战:借助克魔(KeyMob)与常用工具深度洞察App瓶颈

在日常iOS开发过程中&#xff0c;性能问题往往是最令人头疼的一类Bug。尤其是在App上线前的压测阶段或是处理用户反馈的高发期&#xff0c;开发者往往需要面对卡顿、崩溃、能耗异常、日志混乱等一系列问题。这些问题表面上看似偶发&#xff0c;但背后往往隐藏着系统资源调度不当…...

A2A JS SDK 完整教程:快速入门指南

目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库&#xff…...

MySQL 部分重点知识篇

一、数据库对象 1. 主键 定义 &#xff1a;主键是用于唯一标识表中每一行记录的字段或字段组合。它具有唯一性和非空性特点。 作用 &#xff1a;确保数据的完整性&#xff0c;便于数据的查询和管理。 示例 &#xff1a;在学生信息表中&#xff0c;学号可以作为主键&#xff…...

[ACTF2020 新生赛]Include 1(php://filter伪协议)

题目 做法 启动靶机&#xff0c;点进去 点进去 查看URL&#xff0c;有 ?fileflag.php说明存在文件包含&#xff0c;原理是php://filter 协议 当它与包含函数结合时&#xff0c;php://filter流会被当作php文件执行。 用php://filter加编码&#xff0c;能让PHP把文件内容…...

Proxmox Mail Gateway安装指南:从零开始配置高效邮件过滤系统

&#x1f49d;&#x1f49d;&#x1f49d;欢迎莅临我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐&#xff1a;「storms…...