java-使用druid sqlparser将SQL DDL脚本转化为自定义的java对象
java-使用druid sqlparser将SQL DDL脚本转化为自定义的java对象
- 一、引言
- 二、环境
- 三、待解析的DDL
- 四、解析后的对象结构
- 五、完整的UT类
- 六、控制台输出
- 总结
一、引言
在日常开发中,有些需要对SQL进行解析的场景,比如读取表结构信息,生成文档、逆向工程或是生成一些业务代码。例如,当我们需要对Oracle的DDL(数据定义语言)进行解析时,一个强大的SQL语法解析器可以帮助我们直接提取出表的结构信息,包括表名、备注、字段信息以及索引信息。这一功能在以下场景中尤为有用:
- 代码生成:通过解析DDL,我们可以自动生成对应的实体类、数据库访问接口甚至是完整的数据库操作代码,极大地减少了手动编写重复代码的工作量,提高了开发效率。
- 数据库逆向工程:在接手一个遗留系统或者对现有系统进行重构时,通过解析现有的DDL,可以快速地理解和重构数据库模型,为后续的开发工作打下坚实的基础。
- 数据库文档化:自动从DDL中提取表结构信息,可以帮助我们生成数据库文档,使得数据库的设计和结构更加清晰,便于团队成员之间的沟通和协作。
- 数据库迁移:在数据库迁移过程中,解析源数据库的DDL可以帮助我们快速地构建目标数据库的结构,减少迁移过程中的错误和风险。
本文将记录了基于Druid SQLParser这一工具,对DDL进行解析的详细过程。
二、环境
- JDK 17
- Maven依赖
<dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.2.16</version>
</dependency>
三、待解析的DDL
以下内容是基于PowerDesigner做的Oracle 10g的DDL脚本,也是我们需要解析的内容,其中包含drop、create、comment等语句,这里我们只对表、字段信息进行解析。
drop index "Index_1";
drop table "sr_user_info" cascade constraints;
/*==============================================================*/
/* Table: "sr_user_info" */
/*==============================================================*/
create table "sr_user_info" ("user_id" VARCHAR2(64) not null,"type" VARCHAR2(64) not null,"login_name" VARCHAR2(64),"user_name" VARCHAR2(64),"display_name" VARCHAR2(256),"organization" VARCHAR2(64),"region" VARCHAR2(64),"login_count" INTEGER,"request_count" bigint,"status" INTEGER,"last_login_date" DATE,"create_date" DATE,"update_date" DATE,"money" number(9,2),constraint PK_SR_USER_INFO primary key ("user_id")
);
comment on table "sr_user_info" is '记录并统计用户行为';
comment on column "sr_user_info"."user_id" is '用户ID';
comment on column "sr_user_info"."type" is '类型';
comment on column "sr_user_info"."login_name" is '登录名';
comment on column "sr_user_info"."user_name" is '用户名';
comment on column "sr_user_info"."display_name" is '显示名称';
comment on column "sr_user_info"."organization" is '组织结构';
comment on column "sr_user_info"."region" is '区域';
comment on column "sr_user_info"."login_count" is '登录次数';
comment on column "sr_user_info"."request_count" is '请求次数';
comment on column "sr_user_info"."status" is '状态';
comment on column "sr_user_info"."last_login_date" is '最后登录时间';
comment on column "sr_user_info"."create_date" is '创建时间';
comment on column "sr_user_info"."update_date" is '修改时间';
comment on column "sr_user_info"."money" is '金钱';
/*==============================================================*/
/* Index: "Index_1" */
/*==============================================================*/
create unique index "Index_1" on "sr_user_info" ("user_id" ASC,"region" ASC
);
四、解析后的对象结构
以下是DDL解析后的对象结构。
{"TableCode":"sr_user_info","comment":"记录并统计用户行为","columns":[{"colCode":"user_id","comment":"用户ID","length":64,"pk":false,"type":"VARCHAR2"},{"colCode":"type","comment":"类型","length":64,"pk":false,"type":"VARCHAR2"},{"colCode":"login_name","comment":"登录名","length":64,"pk":false,"type":"VARCHAR2"},{"colCode":"user_name","comment":"用户名","length":64,"pk":false,"type":"VARCHAR2"},{"colCode":"display_name","comment":"显示名称","length":256,"pk":false,"type":"VARCHAR2"},{"colCode":"organization","comment":"组织结构","length":64,"pk":false,"type":"VARCHAR2"},{"colCode":"region","comment":"区域","length":64,"pk":false,"type":"VARCHAR2"},{"colCode":"login_count","comment":"登录次数","pk":false,"type":"INTEGER"},{"colCode":"request_count","comment":"请求次数","pk":false,"type":"bigint"},{"colCode":"status","comment":"状态","pk":false,"type":"INTEGER"},{"colCode":"last_login_date","comment":"最后登录时间","pk":false,"type":"DATE"},{"colCode":"create_date","comment":"创建时间","pk":false,"type":"DATE"},{"colCode":"update_date","comment":"修改时间","pk":false,"type":"DATE"},{"colCode":"money","length":9,"pk":false,"precision":2,"type":"number"}]
}
五、完整的UT类
运行下面的单元测试方法ddlParserTest()可以看到完整效果。需要注意的是如果表名、字段名中有些转意字符可以用SQLUtils.normalize(tableName)方法去掉。
import com.alibaba.druid.DbType;
import com.alibaba.druid.sql.SQLUtils;
import com.alibaba.druid.sql.ast.SQLExpr;
import com.alibaba.druid.sql.ast.expr.SQLIntegerExpr;
import com.alibaba.druid.sql.ast.statement.SQLColumnDefinition;
import com.alibaba.druid.sql.ast.statement.SQLCommentStatement;
import com.alibaba.druid.sql.ast.statement.SQLTableElement;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleCreateTableStatement;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OraclePrimaryKey;
import com.alibaba.druid.support.json.JSONUtils;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;import java.util.ArrayList;
import java.util.List;
import java.util.Map;public class SqlParserTest {private String ddl = "";public static class TabInfo{public String TableCode;public String comment;public List<ColumnInfo> columns = new ArrayList<>();}public static class ColumnInfo{public String colCode;public String comment;public String type;public Integer length;public Integer precision;public boolean pk = false;}@Testpublic void ddlParserTest(){//解析DDLvar statements = SQLUtils.parseStatements(ddl,DbType.oracle);//获取索引值java.util.function.BiFunction<List<SQLExpr>,Integer,Integer> getArg=(exprs, index)->{if(exprs==null || exprs.size()<index+1)return null;var expr = exprs.get(index);if(!(expr instanceof SQLIntegerExpr))return null;var intExpr = (SQLIntegerExpr) expr;var n = intExpr.getNumber().intValue();return n;};TabInfo tabInfo = new TabInfo();List<String> pkCols = new ArrayList<>();Map<String,ColumnInfo> colMap = new java.util.HashMap<>();//解析表名java.util.function.Consumer parserCreateTable = (statement) -> {OracleCreateTableStatement table = (OracleCreateTableStatement) statement;var tableName = table.getTableName();tableName = SQLUtils.normalize(tableName);System.out.println("--------------表名------------------");System.out.println("表名\t"+tableName);tabInfo.TableCode = tableName;for (SQLTableElement em : table.getTableElementList()) {if(em instanceof SQLColumnDefinition){var col = (SQLColumnDefinition) em;var colName = col.getColumnName();//字段名colName = SQLUtils.normalize(colName);var dataType = col.getDataType();//数据类型对象var type = dataType.getName();//类型var len = getArg.apply(dataType.getArguments(),0);//长度var precision = getArg.apply(dataType.getArguments(),1);//精度System.out.println(String.format("字段:%s\t%s\t%s\t%s", colName, type, len, precision));//var colInfo = new ColumnInfo();colInfo.colCode = colName;colInfo.type = type;colInfo.length = len;colInfo.precision = precision;colInfo.pk = pkCols.contains(colName);//是否主键字段colMap.put(colName, colInfo);tabInfo.columns.add(colInfo);}else if(em instanceof OraclePrimaryKey){var pk = (OraclePrimaryKey) em;var pkName = pk.getName().getSimpleName();//主键名pkName = SQLUtils.normalize(pkName);//主键字段列表pk.getColumns().forEach(x-> {var colName = x.getExpr().toString();colName = SQLUtils.normalize(colName);pkCols.add(colName);});System.out.println(String.format("主键:%s\t%s\t%s\t%s", pkName, pk.getComment()//注释, pkCols, JSONUtils.toJSONString(pk.getAttributes())));}}};//解析注释java.util.function.Consumer parserComment = (statement) -> {var com = (SQLCommentStatement) statement;System.out.println("------------------注释----------------");if(com.getType() == SQLCommentStatement.Type.TABLE){var tab = com.getOn();var tabName = tab.getName().getSimpleName();//表明var tabComment = com.getComment().toString();//表注释tabComment = SQLUtils.normalize(tabComment);System.out.println(String.format("tab注释:%s\t%s",tabName,tabComment));//tabInfo.comment = tabComment;}else if(com.getType() == SQLCommentStatement.Type.COLUMN){var tab = com.getOn();var tabName = tab.getName().toString();var colName = tab.getName().getSimpleName();//字段名colName = SQLUtils.normalize(colName);var comment = String.valueOf(com.getComment());//字段注释comment = SQLUtils.normalize(comment);System.out.println(String.format("col注释:%s\t%s",colName,comment));//var colInfo = colMap.get(colName);colInfo.comment = comment;}else if(com.getType() == SQLCommentStatement.Type.INDEX){}else if(com.getType() == SQLCommentStatement.Type.VIEW){}else{System.out.println("未知类型"+com.getType());}};//解析语句statements.forEach(statement -> {if(statement instanceof OracleCreateTableStatement){parserCreateTable.accept(statement);}else if(statement instanceof SQLCommentStatement){parserComment.accept(statement);}});System.out.println("\n------------------JSON----------------");String jsonStr = com.alibaba.fastjson.JSON.toJSONString(tabInfo,true);System.out.println(jsonStr);}@BeforeTestpublic void beforeTest() {ddl = "drop index \"Index_1\";\n" +"drop table \"sr_user_info\" cascade constraints;\n" +"/*==============================================================*/\n" +"/* Table: \"sr_user_info\" */\n" +"/*==============================================================*/\n" +"create table \"sr_user_info\" (\n" +" \"user_id\" VARCHAR2(64) not null,\n" +" \"type\" VARCHAR2(64) not null,\n" +" \"login_name\" VARCHAR2(64),\n" +" \"user_name\" VARCHAR2(64),\n" +" \"display_name\" VARCHAR2(256),\n" +" \"organization\" VARCHAR2(64),\n" +" \"region\" VARCHAR2(64),\n" +" \"login_count\" INTEGER,\n" +" \"request_count\" bigint,\n" +" \"status\" INTEGER,\n" +" \"last_login_date\" DATE,\n" +" \"create_date\" DATE,\n" +" \"update_date\" DATE,\n" +" \"money\" number(9,2),\n" +" constraint PK_SR_USER_INFO primary key (\"user_id\")\n" +");\n" +"comment on table \"sr_user_info\" is '记录并统计用户行为';\n" +"comment on column \"sr_user_info\".\"user_id\" is '用户ID';\n" +"comment on column \"sr_user_info\".\"type\" is '类型';\n" +"comment on column \"sr_user_info\".\"login_name\" is '登录名';\n" +"comment on column \"sr_user_info\".\"user_name\" is '用户名';\n" +"comment on column \"sr_user_info\".\"display_name\" is '显示名称';\n" +"comment on column \"sr_user_info\".\"organization\" is '组织结构';\n" +"comment on column \"sr_user_info\".\"region\" is '区域';\n" +"comment on column \"sr_user_info\".\"login_count\" is '登录次数';\n" +"comment on column \"sr_user_info\".\"request_count\" is '请求次数';\n" +"comment on column \"sr_user_info\".\"status\" is '状态';\n" +"comment on column \"sr_user_info\".\"last_login_date\" is '最后登录时间';\n" +"comment on column \"sr_user_info\".\"create_date\" is '创建时间';\n" +"comment on column \"sr_user_info\".\"update_date\" is '修改时间';\n" +"comment on column \"sr_user_info\".\"money\" is '金钱';\n" +"/*==============================================================*/\n" +"/* Index: \"Index_1\" */\n" +"/*==============================================================*/\n" +"create unique index \"Index_1\" on \"sr_user_info\" (\n" +" \"user_id\" ASC,\n" +" \"region\" ASC\n" +");\n"; }
}
六、控制台输出
--------------表名------------------
表名 sr_user_info
字段:user_id VARCHAR2 64 null
字段:type VARCHAR2 64 null
字段:login_name VARCHAR2 64 null
字段:user_name VARCHAR2 64 null
字段:display_name VARCHAR2 256 null
字段:organization VARCHAR2 64 null
字段:region VARCHAR2 64 null
字段:login_count INTEGER null null
字段:request_count bigint null null
字段:status INTEGER null null
字段:last_login_date DATE null null
字段:create_date DATE null null
字段:update_date DATE null null
字段:money number 9 2
主键:PK_SR_USER_INFO null [user_id] {}
------------------注释----------------
tab注释:"sr_user_info" 记录并统计用户行为
col注释:user_id 用户ID
col注释:type 类型
col注释:login_name 登录名
col注释:user_name 用户名
col注释:display_name 显示名称
col注释:organization 组织结构
col注释:region 区域
col注释:login_count 登录次数
col注释:request_count 请求次数
col注释:status 状态
col注释:last_login_date 最后登录时间
col注释:create_date 创建时间
col注释:update_date 修改时间
总结
不同的DDL定义语法会解析为不同的statment对象,这里只演示了一种DDL格式,比较原生。开源项目中有些很多测试用例其中继承OracleSchemaStatVisitor解析,看着内聚性更强。还需要注意的是,有些DDL将字段注释写在create语句中,上面的代码还要做相应的修改。
相关文章:
java-使用druid sqlparser将SQL DDL脚本转化为自定义的java对象
java-使用druid sqlparser将SQL DDL脚本转化为自定义的java对象 一、引言二、环境三、待解析的DDL四、解析后的对象结构五、完整的UT类六、控制台输出总结 一、引言 在日常开发中,有些需要对SQL进行解析的场景,比如读取表结构信息,生成文档、…...
靜態IP與DHCP的區別和用法
IP地址可以是靜態的,即固定不變,也可以是動態的,定期更改或每次連接後更改。 什麼是靜態 IP? 靜態IP地址是固定的,手動分配的IP地址,不會隨時間而變化。分配後,此 IP 保持不變,並由…...
【C#】Debug和Release的区别和使用
在 C 或 C# 开发中,Debug 和 Release 是两种不同的编译配置,主要用于开发过程中的不同阶段。它们的主要区别如下: 1. Debug 版本 Debug 版本是为了开发和调试程序而优化的构建模式。 特点: 包含调试信息: Debug 版本…...
Element plus 下拉框组件选中一个选项后显示的是 value 而不是 label
最近刚进行 Vue3 Element plus 项目实践,在进行表单二次封装的时候,表单元素 select 下拉框组件选中一个选项后显示的是 value 而不是 label,下面上代码: 原来的写法: <el-selectv-if"v.type select"…...
Redis - 消息队列 Stream
一、概述 消息队列 定义 消息队列模型:一种分布式系统中的消息传递方案,由消息队列、生产者和消费者组成消息队列:负责存储和管理消息的中间件,也称为消息代理(Message Broker)生产者:负责 产…...
【多维DP】【hard】力扣1269. 停在原地的方案数
有一个长度为 arrLen 的数组,开始有一个指针在索引 0 处。 每一步操作中,你可以将指针向左或向右移动 1 步,或者停在原地(指针不能被移动到数组范围外)。 给你两个整数 steps 和 arrLen ,请你计算并返回&…...
Android显示系统(11)- 向SurfaceFlinger申请Surface
Android显示系统(01)- 架构分析 Android显示系统(02)- OpenGL ES - 概述 Android显示系统(03)- OpenGL ES - GLSurfaceView的使用 Android显示系统(04)- OpenGL ES - Shader绘制三角…...
OpenCV实验篇:识别图片颜色并绘制轮廓
第三篇:识别图片颜色并绘制轮廓 1. 实验原理 颜色识别的原理: 颜色在图像处理中通常使用 HSV 空间来表示。 HSV 空间是基于人类视觉系统的一种颜色模型,其中: H(Hue):色调,表示颜色…...
鸿蒙-应用内悬浮窗
//悬浮窗工具类 import { window } from kit.ArkUI; import { BusinessError } from kit.BasicServicesKit; import { Logger } from mbbase/common-ui; import * as FloatedWindowPage from ./FloatedWindowPage; // 导入命名路由页面 const TAG [FloatedWindowUtils]; ex…...
Ubuntu Linux操作系统
一、Ubuntu简介 Ubuntu Linux是由南非人马克沙特尔沃思(Mark Shuttleworth)创办的基于Debian Linux的操作系统,于2004年10月公布。Ubuntu是一个以桌面应用为主的Linux发行版操作系统。Ubuntu拥有庞大的社区力量,用户可以方便地从社区获得帮助。其官方网…...
Linux下SVN客户端保存账号密码
参考文章:解决:Linux上SVN 1.12版本以上无法直接存储明文密码_linux svn 保存密码-CSDN博客新版本svn使用gpg-agent存储密码-CSDN博客svn之无法让 SVN 存储密码,即使配置设置为允许_编程设计_ITGUEST 方法一:明文方式保存密码 首…...
【DBeaver】连接带kerberos的hive[Apache|HDP]
目录 一、安装配置Kerberos客户端环境 1.1 安装Kerberos客户端 1.2 环境配置 二、基于Cloudera驱动创建连接 三、基于Hive原生驱动创建连接 一、安装配置Kerberos客户端环境 1.1 安装Kerberos客户端 在Kerberos官网下载,地址如下:https://web.mit.edu/kerberos…...
Android-Glide详解
目录 一,介绍 二,使用 三,源码分析思路 四,with源码分析 五,模拟Glide生命周期管理 一,介绍 Glide目前是安卓最主流的加载图片的框架,也是源码最为复杂的框架之一。 要想完完全全吃透Glide的源…...
【容器】k8s学习笔记原理详解(十万字超详细)
Pod详解 Pod介绍 Pod结构 每个Pod中都可以包含一个或者多个容器,这些容器可以分为两类: 用户程序所在的容器,数量可多可少Pause容器,这是每个Pod都会有的一个根容器,它的作用有两个: 可以以它为依据&am…...
SQL Server通过存储过程实现自定义邮件格式并定时发送
在 SQL Server 中,可以通过存储过程实现自定义邮件格式并定时发送。这通常涉及以下几个步骤: 1. 配置 Database Mail:首先需要配置 SQL Server 的 Database Mail 功能。 2. 创建存储过程:编写存储过程来生成自定义邮件格式并发送邮件。 3. 设置 SQL Server 代理作…...
通过增强的 vSphere 集成增强你的 vSphere 监控
作者:来自 Elastic Ishleen Kaur•Lalit Satapathy vSphere 是 VMware 的云计算虚拟化平台,提供一套功能强大的虚拟化资源管理套件。它允许组织创建、管理和优化虚拟环境,提供高可用性、负载平衡和简化资源分配等高级功能。vSphere 可以高效利…...
C++ 并发专题 - C++线程同步的几种方法
一:概述 线程同步是多线程编程中的一个重要概念,它用于控制多个线程之间对共享资源的访问,避免竞态条件(race condition)和数据不一致的问题。线程同步确保在多线程环境中,多个线程访问共享数据时能够按照某…...
[java]网络编程
java.net.*包下提供了网络编程的解决方案 通信架构 CS架构 客户端 客户端需要开发 用户需要安装 服务端 需要开发 BS架构 浏览器 不需要开发 需要安装浏览器 服务器 需要开发 网络通信三要素 IP地址 是设备在网络中的唯一标识, 全称 互联网协议地址 分类 公网IP 可…...
[C++]类的继承
一、什么是继承 1.定义: 在 C 中,继承是一种机制,允许一个类(派生类)继承另一个类(基类)的成员(数据和函数)。继承使得派生类能够直接访问基类的公有和保护成员…...
2024安装hexo和next并部署到github和服务器最新教程
碎碎念 本来打算写点算法题上文所说的题目,结果被其他事情吸引了注意力。其实我之前也有过其他博客网站,但因为长期不维护,导致数据丢失其实是我懒得备份。这个博客现在部署在GitHub Pages上,github不倒,网站不灭&…...
【spring】@Qualifier注解
目录 1. 说明2. 用法示例2.1 标注在字段上2.2 标注在方法上2.3 标注在类上2.4 在自定义注解上的应用 3. 注意事项 1. 说明 1.Qualifier是Spring框架中的一个注解,主要用于解决依赖注入时的歧义性问题。2.定义:Qualifier是一个限定符注解,用于…...
uniapp 应用的生命周期、页面的生命周期、组件的生命周期
uniapp 作为一款跨平台的移动应用开发框架,其生命周期分为应用生命周期、页面生命周期和组件生命周期。下面分别介绍这三种生命周期的具体内容: 应用生命周期 应用生命周期仅适用于整个应用,在 App.vue 中可以监听到以下生命周期函数&#…...
热更新解决方案4——xLua热补丁
概述 运行时不在执行C#中的代码,而是执行Lua中的代码,相当于是打了个补丁。 1.第一个热补丁 2.多函数替换 3.协程函数替换 在原HotfixMain脚本中只加个协程函数即可(和在Start中启动协程函数) 4.索引器和属性替换 在HotfixMain中…...
【MARL】深入理解多智能体近端策略优化(MAPPO)算法与调参
📢本篇文章是博主强化学习(RL)领域学习时,用于个人学习、研究或者欣赏使用,并基于博主对相关等领域的一些理解而记录的学习摘录和笔记,若有不当和侵权之处,指出后将会立即改正,还望谅…...
3.2.1.2 汇编版 原子操作 CAS
基本原理说明 在 x86 和 ARM 架构上,原子操作通常利用硬件提供的原子指令来实现,比如 LOCK 前缀(x86)或 LDREX/STREX(ARM)。以下是一些关键的原子操作(例如原子递增和比较交换)的汇…...
关于llama2:从原始llama-2-7b到llama-2-7b-hf的权重转换教程
1.首先,我是从各个教程里面选了一个实际操作的教程(这样更加靠谱):下载llama2-7b并转hf模型_huggingface 下载llama2-7b-chat-hf-CSDN博客 2.但是,其实我在另外一篇更好的教程里面看到过一个坑(这篇好像是腾…...
物理机内网穿透
前言: 本文主要讲述如何使用内网穿透以及其安全性。 将带领大家在公网上搭建几个常用靶场。 一,什么是内网穿透。 大多数情况下,我们的个人电脑都处于内网,即没有可公开访问的独立 IP 地址,因此其他内网用户找不到…...
构建一个rust生产应用读书笔记四(实战1)
我们需要从访客那里收集哪些信息,以便将其登记为电子邮件通讯的订阅者? 电子邮件地址:这是最基本的要求,因为我们需要通过电子邮件地址向订阅者发送内容。姓名:虽然这不是强制性的,但我们希望收集一个名字…...
[LeetCode-Python版]206. 反转链表(迭代+递归两种解法)
题目 给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。 示例 1: 输入:head [1,2,3,4,5] 输出:[5,4,3,2,1] 示例 2: 输入:head [1,2] 输出:[2,1] 示例 3࿱…...
shardingsphere分库分表跨库访问 添加分片规则
shardingsphere分库分表跨库访问 添加分片规则 建立 JDBC 环境 创建表 t_order: CREATE TABLE t_order (tid bigint(20) NOT NULL,tname varchar(255) DEFAULT NULL,goods_id bigint(20) DEFAULT NULL,tstatus varchar(255) DEFAULT NULL,PRIMARY KEY (tid) ) E…...
【NLP 15、深度学习处理文本】
目录 一、反向传播 编辑 1.反向传播运算过程 2.前向传播和反向传播的作用 前向传播 反向传播 3.定义模型(torch包) 4.手动实现 ① 线性层 ② sigmoid激活函数 ③ 手动实现MSE均方差损失函数 ④ 前向传播 ⑤ 手动实现梯度计算 ⑤ 权重的更新:…...
Android Studio创建新项目并引入第三方so外部aar库驱动NFC读写器读写IC卡
本示例使用设备:https://item.taobao.com/item.htm?spma21dvs.23580594.0.0.52de2c1bbW3AUC&ftt&id615391857885 一、打开Android Studio,点击 File> New>New project 菜单,选择 要创建的项目模版,点击 Next 二、输入项目名称…...
3D视觉[一]3D计算机视觉
3D视觉[一]3D计算机视觉 3D计算机视觉概述 像机标定 文章目录 3D视觉[一]3D计算机视觉前言一、人类视觉二、计算机视觉2.1 计算机视觉的研究目的2.2 计算机视觉的研究任务2.3 计算机视觉的研究方法2.4 视觉计算理论2.5 马尔框架中计算机视觉表达的四个层次2.5.1 图像ÿ…...
Linux权限(超详细彻底搞懂Linux的权限)
🔥个人主页🔥:孤寂大仙V 🌈收录专栏🌈:Linux 🌹往期回顾🌹:Linux常见指令(初学者必看) 🔖流水不争,争的是滔滔不 一、Linux下的两种用户超级用户&…...
Ubuntu22.04安装docker desktop遇到的bug
1. 确认已启用 KVM 虚拟化 如果加载了模块,输出应该如下图。说明 Intel CPU 的 KVM 模块已开启。 否则在VMware开启宿主机虚拟化功能: 2. 下一步操作: Ubuntu | Docker Docs 3. 启动Docker桌面后发现账户登陆不上去: Sign in | …...
网新恒天八股总结
Java的基本数据类型 四类八种 整数类型:byte,short,int,long 浮点类型:float,double 字符类型:char 布尔类型:boolean char类型的范围 0 ~ 65535,可以表示16位无符号整数 equals和的区别 &,&&a…...
【AIGC】与模型对话:理解与预防ChatGPT中的常见误解
博客主页: [小ᶻ☡꙳ᵃⁱᵍᶜ꙳] 本文专栏: AIGC | ChatGPT 文章目录 💯前言💯模型的工作原理和用户期望差异人工智能模型的基本工作原理认知上的局限与误解用户期望与模型实际能力的差距精确理解用户意图的重要性实际应用中的建议 &…...
09篇--图片的水印添加(掩膜的运用)
如何添加水印? 添加水印其实可以理解为将一张图片中的某个物体或者图案提取出来,然后叠加到另一张图片上。具体的操作思想是通过将原始图片转换成灰度图,并进行二值化处理,去除背景部分,得到一个类似掩膜的图像。然后…...
Qt 使用modbus协议
Qt 框架下 使用modbus协议 一,使用Qt原生的 QModbusClient ,比如QModbusTcpClient 1,因为modbus的读写 需要在同一个线程中,所以需要在主线程中利用moveToThread的方式,将业务逻辑封装到 子线程中。 2,m…...
pip离线安装一个github仓库
要使用pip安装一个本地Git仓库,你可以按照以下步骤操作: 确保你已经克隆了Git仓库到本地。 进入仓库所在的目录。 使用pip安装。 以下是具体的命令: 克隆Git仓库到本地(替换下面的URL为你的仓库URL) git clone https…...
【ETCD】【源码阅读】深入分析 storeTxnWrite.Put方法源码
该方法是 storeTxnWrite 类型中的核心方法,负责将键值对存储到数据库,同时处理键的元数据(如版本、修订号、租约)并管理租约关联。 目录 一、完整代码二、方法详解方法签名1. 计算修订号并初始化变量2. 检查键是否已存在3. 生成索…...
桥接模式的理解和实践
桥接模式(Bridge Pattern),又称桥梁模式,是一种结构型设计模式。它的核心思想是将抽象部分与实现部分分离,使它们可以独立地进行变化,从而提高系统的灵活性和可扩展性。本文将详细介绍桥接模式的概念、原理…...
【Rust自学】3.2. 数据类型:标量类型
3.2.0. 写在正文之前 欢迎来到Rust自学的第三章,一共有6个小节,分别是: 变量与可变性数据类型:标量类型(本文)数据类型:复合类型函数和注释控制流:if else控制流:循环 通过第二章…...
【Leetcode Top 100】199. 二叉树的右视图
问题背景 给定一个二叉树的 根节点 r o o t root root,想象自己站在它的右侧,按照从顶部到底部的顺序,返回从右侧所能看到的节点值。 数据约束 二叉树的节点个数的范围是 [ 0 , 100 ] [0,100] [0,100] − 100 ≤ N o d e . v a l ≤ 100…...
Java并发编程框架之其他并发工具
选错了就选错了,不要一遍一遍的后悔,总是一遍遍的想,当时怎么样就好了,不要欺负当时的自己,当时你一个人站在迷雾中,也很迷茫,就算重新来一遍,以你当时的阅历和心智,还是…...
MinerU:PDF文档提取工具
目录 docker一键启动本地配置下载模型权重文件demo.py使用命令行启动GPU使用情况 wget https://github.com/opendatalab/MinerU/raw/master/Dockerfile docker build -t mineru:latest .docker一键启动 有点问题,晚点更新 本地配置 就是在Python环境中配置依赖和…...
Unity性能优化---使用SpriteAtlas创建图集进行批次优化
在日常游戏开发中,UI是不可缺少的模块,而在UI中又使用着大量的图片,特别是2D游戏还有很多精灵图片存在,如果不加以处理,会导致很高的Batches,影响性能。 比如如下的例子: Batches是9࿰…...
wazuh-modules-sca-scan
sca模块主函数wm_sca_main -> wm_sca_start 检查policy文件中的每一个项目wm_sca_check_policy static int wm_sca_check_policy(const cJSON * const policy, const cJSON * const checks, OSHash *global_check_list) {if(!policy) {return 1;}const cJSON * const id c…...
力扣-图论-15【算法学习day.65】
前言 ###我做这类文章一个重要的目的还是给正在学习的大家提供方向和记录学习过程(例如想要掌握基础用法,该刷哪些题?)我的解析也不会做的非常详细,只会提供思路和一些关键点,力扣上的大佬们的题解质量是非…...
JS萤石云录像回放拖动进度条无法正常播放
问题描述: 本项目版本:vue2.6.12,webpack3.6.0,ezuikit-js0.7.2 在使用萤石云的JavaScript SDK做监控的直播、录像回放时,遇到部分设备的录像回放,无法根据控制面板的拖动进度条查看某时间段的录像。 官方…...