JSqlParser的使用

简介

        JSqlParse是一款很精简的sql解析工具,它可以将常用的sql文本解析成具有层级结构的语法树,我们可以针对解析后的节点进行处理(增加、移除、修改等操作),从而生成符合我们业务要求的sql,比如添加过滤条件等等

     JSqlParse采用访问者模式

项目简介

        

项目结构非常简单,从截图上看就5个包。如果对源码感兴趣的可以直接从github上下载源码包调试。其中expression包包含了所有的sql表达式的抽象对象:

statement包含了所有sql语句的类型,比如:增删改查,ddl语句,rollback语句等等

schema包是对数据库基本单元的抽象:服务器、数据库、表、列等等

parser包是整个解析的核心逻辑,感兴趣的可以自行源码调试

使用示例

        上面已经做了关于该解析工具的简单介绍,对于工具类,最重要的使用。以下举例关于增、删、改、查的sql语句中,均增加一列为例介绍该工具的简单使用

依赖引入

<dependency><groupId>com.github.jsqlparser</groupId><artifactId>jsqlparser</artifactId><version>4.5</version>
</dependency>

新增add

原始sql:insert into t_user_info(id,user_name,address) values('123','zhangsan','龙华')

期望在执行该sql时,能增加一列STATUS作为插入

都是一些api的运用,相关代码如下:

package com.lyc.boot.client.test.insert;import com.lyc.boot.client.test.insert.visitor.InsertStatementVisitor;
import lombok.extern.slf4j.Slf4j;
import net.sf.jsqlparser.JSQLParserException;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.RowConstructor;
import net.sf.jsqlparser.expression.StringValue;
import net.sf.jsqlparser.expression.operators.relational.ExpressionList;
import net.sf.jsqlparser.expression.operators.relational.ItemsList;
import net.sf.jsqlparser.parser.CCJSqlParserUtil;
import net.sf.jsqlparser.schema.Column;
import net.sf.jsqlparser.statement.Statement;
import net.sf.jsqlparser.statement.insert.Insert;
import net.sf.jsqlparser.statement.select.Select;
import net.sf.jsqlparser.statement.select.SelectBody;
import net.sf.jsqlparser.statement.select.SetOperationList;
import net.sf.jsqlparser.statement.values.ValuesStatement;import java.util.List;import static com.lyc.boot.client.test.CommonUtil.printStatement;
import static com.lyc.boot.client.test.CommonUtil.printTableName;@Slf4j
public class InsertCommonTest {private static final String INSERT_COMMON = "insert into t_user_info(id,user_name,address) values('123','zhangsan','龙华')";public static void main(String[] args) throws JSQLParserException {useCommonAddColumn();
//        useVisitorAddColumn();}private static void useCommonAddColumn() throws JSQLParserException {Statement statement = CCJSqlParserUtil.parse(INSERT_COMMON);printStatement(statement);if (statement instanceof Insert) {Insert insert = (Insert)statement;printTableName(insert.getTable());List<Column> columns = insert.getColumns();columns.add(new Column("STATUS"));Select select = insert.getSelect();SelectBody selectBody = select.getSelectBody();if (selectBody instanceof SetOperationList) {SetOperationList operationList = (SetOperationList)selectBody;List<SelectBody> selects = operationList.getSelects();for (SelectBody body : selects) {if (body instanceof ValuesStatement) {ValuesStatement valuesStatement = (ValuesStatement)body;ItemsList itemsList = valuesStatement.getExpressions();if(itemsList instanceof ExpressionList) {ExpressionList expressionList = (ExpressionList)itemsList;List<Expression> expressions = expressionList.getExpressions();for (Expression expression : expressions) {if(expression instanceof RowConstructor) {RowConstructor rowConstructor = (RowConstructor)expression;ExpressionList exprList = rowConstructor.getExprList();List<Expression> rowConstructorExList = exprList.getExpressions();rowConstructorExList.add(new StringValue("0"));}}}}}}}printStatement(statement);}/*** 使用访问者方式增加insert的column** @throws JSQLParserException*/private static void useVisitorAddColumn() throws JSQLParserException {Statement statement = CCJSqlParserUtil.parse(INSERT_COMMON);printStatement(statement);statement.accept(new InsertStatementVisitor());printStatement(statement);}}
package com.lyc.boot.client.test.insert.visitor;import net.sf.jsqlparser.schema.Column;
import net.sf.jsqlparser.statement.StatementVisitorAdapter;
import net.sf.jsqlparser.statement.insert.Insert;
import net.sf.jsqlparser.statement.select.Select;
import net.sf.jsqlparser.statement.select.SelectBody;import java.util.List;import static com.lyc.boot.client.test.CommonUtil.printTableName;public class InsertStatementVisitor extends StatementVisitorAdapter {@Overridepublic void visit(Insert insert) {printTableName(insert.getTable());List<Column> columns = insert.getColumns();columns.add(new Column("status"));Select select = insert.getSelect();SelectBody selectBody = select.getSelectBody();selectBody.accept(new InsertSelectVisitor());}
}
package com.lyc.boot.client.test.insert.visitor;import net.sf.jsqlparser.expression.operators.relational.ItemsList;
import net.sf.jsqlparser.statement.select.SelectBody;
import net.sf.jsqlparser.statement.select.SelectVisitorAdapter;
import net.sf.jsqlparser.statement.select.SetOperationList;
import net.sf.jsqlparser.statement.values.ValuesStatement;import java.util.List;public class InsertSelectVisitor extends SelectVisitorAdapter {@Overridepublic void visit(SetOperationList setOpList) {List<SelectBody> selects = setOpList.getSelects();for (SelectBody body : selects) {body.accept(this);}}@Overridepublic void visit(ValuesStatement valuesStatement) {ItemsList itemsList = valuesStatement.getExpressions();itemsList.accept(new InsertItemsListVisitor());}
}
package com.lyc.boot.client.test.insert.visitor;import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.operators.relational.ExpressionList;
import net.sf.jsqlparser.util.validation.validator.ItemsListValidator;import java.util.List;public class InsertItemsListVisitor extends ItemsListValidator {@Overridepublic void visit(ExpressionList expressionList) {List<Expression> expressions = expressionList.getExpressions();for (Expression expression : expressions) {expression.accept(new InsertExpressionVisitor());}}
}
package com.lyc.boot.client.test.insert.visitor;import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.ExpressionVisitorAdapter;
import net.sf.jsqlparser.expression.RowConstructor;
import net.sf.jsqlparser.expression.StringValue;
import net.sf.jsqlparser.expression.operators.relational.ExpressionList;import java.util.List;public class InsertExpressionVisitor extends ExpressionVisitorAdapter {@Overridepublic void visit(RowConstructor rowConstructor) {ExpressionList exprList = rowConstructor.getExprList();List<Expression> expressions = exprList.getExpressions();expressions.add(new StringValue("0"));}
}

      以上是关于新增sql增加一列作为插入的简单运用,其中有通过类型判断处理和通过访问者模式处理(基于java多态实现),最终打印的结果如下:

删除delete

原sql:delete from t_user_info where user_name = ? and addres = ?

期望在删除时增加过滤条件STATUS='0'

相关代码如下:

package com.lyc.boot.client.test.delete;import com.lyc.boot.client.test.delete.visitor.DeleteStatementVisitor;
import lombok.extern.slf4j.Slf4j;
import net.sf.jsqlparser.JSQLParserException;
import net.sf.jsqlparser.parser.CCJSqlParserUtil;
import net.sf.jsqlparser.statement.Statement;
import net.sf.jsqlparser.statement.delete.Delete;import static com.lyc.boot.client.test.CommonUtil.printStatement;@Slf4j
public class DeleteCommonTest {private static final String DELETE_COMMON = "delete from t_user_info where user_name = ? and addres = ?";public static void main(String[] args) throws JSQLParserException {
//        commonAddColumn();visitorAddColumn();}private static void visitorAddColumn() throws JSQLParserException{Statement statement = CCJSqlParserUtil.parse(DELETE_COMMON);printStatement(statement);statement.accept(new DeleteStatementVisitor());printStatement(statement);}private static void commonAddColumn() throws JSQLParserException {Statement statement = CCJSqlParserUtil.parse(DELETE_COMMON);printStatement(statement);if(statement instanceof Delete) {Delete delete = (Delete)statement;DeleteStatementVisitor.addColumn(delete);}printStatement(statement);}
}

package com.lyc.boot.client.test.delete.visitor;import com.lyc.boot.client.test.CommonUtil;
import lombok.extern.slf4j.Slf4j;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.Parenthesis;
import net.sf.jsqlparser.expression.StringValue;
import net.sf.jsqlparser.expression.operators.conditional.AndExpression;
import net.sf.jsqlparser.expression.operators.relational.EqualsTo;
import net.sf.jsqlparser.schema.Column;
import net.sf.jsqlparser.statement.StatementVisitorAdapter;
import net.sf.jsqlparser.statement.delete.Delete;import java.util.Objects;@Slf4j
public class DeleteStatementVisitor extends StatementVisitorAdapter {@Overridepublic void visit(Delete delete) {addColumn(delete);}public static void addColumn(Delete delete) {CommonUtil.printTableName(delete.getTable());Expression where = delete.getWhere();Parenthesis parenthesis = new Parenthesis(new EqualsTo(new Column("STATUS"), new StringValue("1")));if (Objects.isNull(where)) {delete.setWhere(parenthesis);} else {delete.setWhere(new AndExpression(where,parenthesis));}}
}

执行结果如下图:

修改update

原sql为:update t_user_info set user_name = ?,address = ? where id = ? and score = ?

期望在修改时set增加STATUS = ? where条件增加STATUS = '1'

package com.lyc.boot.client.test.update;import com.lyc.boot.client.test.update.visitor.UpdateStatementVisitor;
import lombok.extern.slf4j.Slf4j;
import net.sf.jsqlparser.JSQLParserException;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.JdbcParameter;
import net.sf.jsqlparser.expression.Parenthesis;
import net.sf.jsqlparser.expression.StringValue;
import net.sf.jsqlparser.expression.operators.conditional.AndExpression;
import net.sf.jsqlparser.expression.operators.relational.EqualsTo;
import net.sf.jsqlparser.parser.CCJSqlParserUtil;
import net.sf.jsqlparser.schema.Column;
import net.sf.jsqlparser.schema.Table;
import net.sf.jsqlparser.statement.Statement;
import net.sf.jsqlparser.statement.update.Update;
import net.sf.jsqlparser.statement.update.UpdateSet;import java.util.ArrayList;
import java.util.Objects;import static com.lyc.boot.client.test.CommonUtil.printStatement;/*** update语句修改***/
@Slf4j
public class UpdateCommonTest {private static final String COMMON_UPDATE = "update t_user_info set user_name = ?,address = ? where id = ? and score = ?";public static void main(String[] args) throws JSQLParserException {
//        commonUpdateAddColumn();visitorAddColumn();}private static void visitorAddColumn() throws JSQLParserException{Statement statement = CCJSqlParserUtil.parse(COMMON_UPDATE);printStatement(statement);statement.accept(new UpdateStatementVisitor());printStatement(statement);}private static void commonUpdateAddColumn() throws JSQLParserException {Statement statement = CCJSqlParserUtil.parse(COMMON_UPDATE);printStatement(statement);if(statement instanceof Update) {Update update = (Update)statement;Table table = update.getTable();ArrayList<UpdateSet> updateSets = update.getUpdateSets();Column column = new Column("STATUS");StringValue stringValue = new StringValue("?");JdbcParameter jdbcParameter = new JdbcParameter();UpdateSet updateSet = new UpdateSet(column,jdbcParameter);updateSets.add(updateSet);Expression whereExpression = update.getWhere();EqualsTo equalsTo = new EqualsTo(new Column("STATUS"), new StringValue("1"));Parenthesis parenthesis = new Parenthesis(equalsTo);if (Objects.isNull(whereExpression)) {update.setWhere(parenthesis);} else {update.setWhere(new AndExpression(whereExpression,parenthesis));}}printStatement(statement);}}
package com.lyc.boot.client.test.update.visitor;import com.lyc.boot.client.test.CommonUtil;
import lombok.extern.slf4j.Slf4j;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.JdbcParameter;
import net.sf.jsqlparser.expression.Parenthesis;
import net.sf.jsqlparser.expression.StringValue;
import net.sf.jsqlparser.expression.operators.conditional.AndExpression;
import net.sf.jsqlparser.expression.operators.relational.EqualsTo;
import net.sf.jsqlparser.schema.Column;
import net.sf.jsqlparser.schema.Table;
import net.sf.jsqlparser.statement.StatementVisitorAdapter;
import net.sf.jsqlparser.statement.update.Update;
import net.sf.jsqlparser.statement.update.UpdateSet;import java.util.ArrayList;
import java.util.Objects;@Slf4j
public class UpdateStatementVisitor extends StatementVisitorAdapter {@Overridepublic void visit(Update update) {CommonUtil.printTableName(update.getTable());ArrayList<UpdateSet> updateSets = update.getUpdateSets();UpdateSet statusUpdateSet = new UpdateSet(new Column("STATUS"), new JdbcParameter());updateSets.add(statusUpdateSet);Expression where = update.getWhere();Parenthesis parenthesis = new Parenthesis(new EqualsTo(new Column("STATUS"), new StringValue("1")));if (Objects.isNull(where)) {update.setWhere(parenthesis);} else {update.setWhere(new AndExpression(where,parenthesis));}}
}

执行结果如下图所示:

查询select

原sql如下:select id as id,user_name as userName,address as address from t_user_info where id = ? and user_name = ? order by create_time desc

期望在查询时增加where的过滤条件STATUS = '1'

package com.lyc.boot.client.test.select;import com.lyc.boot.client.test.select.visitor.SelectSelectVisitor;
import com.lyc.boot.client.test.select.visitor.SelectStatementVisitor;
import lombok.extern.slf4j.Slf4j;
import net.sf.jsqlparser.JSQLParserException;
import net.sf.jsqlparser.parser.CCJSqlParserUtil;
import net.sf.jsqlparser.statement.Statement;
import net.sf.jsqlparser.statement.select.*;import static com.lyc.boot.client.test.CommonUtil.printStatement;@Slf4j
/*** 给查询条件添加更多的过滤条件** and status = '1'*/
public class SelectCommonTest {private static final String SELECT_COMMON = "select id as id,user_name as userName,address as address from t_user_info where id = ? and user_name = ? order by create_time desc";public static void main(String[] args) throws JSQLParserException {
//        commonSelectAddWhere();visitorSelectAddWhere();}private static void visitorSelectAddWhere() throws JSQLParserException{Statement statement = CCJSqlParserUtil.parse(SELECT_COMMON);printStatement(statement);statement.accept(new SelectStatementVisitor());printStatement(statement);}private static void commonSelectAddWhere() throws JSQLParserException {Statement statement = CCJSqlParserUtil.parse(SELECT_COMMON);printStatement(statement);if (statement instanceof Select) {Select select = (Select)statement;SelectBody selectBody = select.getSelectBody();if (selectBody instanceof PlainSelect) {PlainSelect plainSelect = (PlainSelect)selectBody;SelectSelectVisitor.setWhereExpression(plainSelect);}}printStatement(statement);}}
package com.lyc.boot.client.test.select.visitor;import net.sf.jsqlparser.statement.StatementVisitorAdapter;
import net.sf.jsqlparser.statement.select.Select;
import net.sf.jsqlparser.statement.select.SelectBody;public class SelectStatementVisitor extends StatementVisitorAdapter {@Overridepublic void visit(Select select) {SelectBody selectBody = select.getSelectBody();selectBody.accept(new SelectSelectVisitor());}
}
package com.lyc.boot.client.test.select.visitor;import com.lyc.boot.client.test.CommonUtil;
import lombok.extern.slf4j.Slf4j;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.Parenthesis;
import net.sf.jsqlparser.expression.StringValue;
import net.sf.jsqlparser.expression.operators.conditional.AndExpression;
import net.sf.jsqlparser.expression.operators.relational.EqualsTo;
import net.sf.jsqlparser.schema.Column;
import net.sf.jsqlparser.schema.Table;
import net.sf.jsqlparser.statement.select.PlainSelect;
import net.sf.jsqlparser.statement.select.SelectVisitorAdapter;import java.util.List;
import java.util.Objects;@Slf4j
public class SelectSelectVisitor extends SelectVisitorAdapter {@Overridepublic void visit(PlainSelect plainSelect) {setWhereExpression(plainSelect);}public static void setWhereExpression(PlainSelect plainSelect) {Expression where = plainSelect.getWhere();EqualsTo equalsTo = new EqualsTo(new Column("STATUS"), new StringValue("1"));Parenthesis parenthesis = new Parenthesis(equalsTo);if (Objects.isNull(where)) {plainSelect.setWhere(parenthesis);} else {AndExpression andExpression = new AndExpression(where, parenthesis);plainSelect.setWhere(andExpression);}}
}

执行结果如下图:

扩展简析

jsqlParser的实际之一就是在mybaits-plus中的各种插件,比如:多租户插件com.baomidou.mybatisplus.extension.plugins.inner.TenantLineInnerInterceptor

该插件的作用是:在执行sql时在where条件处增加了过滤条件(默认是tenant_id = ?,具体的字段可以自己配置实现)

当配置了MybatisPlusInterceptor,并且添加了TenantLineInnerInterceptor时,在执行sql时会被该拦截器拦截,具体的源码流程如下:

当执行查询语句时,sql会被MybatisPlusInterceptor插件拦截,插件调TenantLineInnerInterceptor的beforeQuery方法触发

其中BaseMultiTableInnerInterceptor是JsqlParserSupport的子类,提供了模板方法用于修改sql

图上,生成的sql由com.baomidou.mybatisplus.extension.parser.JsqlParserSupport#parserSingle方法决定

最终执行sql解析完成添加过滤条件的操作:

在TenantLineInnerInterceptor插件中,最终是在where结尾出添加了(默认)tenant_id = xxxx的过滤条件,完成多租户数据隔离处理的。具体的源码逻辑可以调试根据

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

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

相关文章

全智能深度演进,一键成片让视频创作颠覆式提效

全智能一键成片&#xff0c;让内容创作的「边际成本」逼近于零。 大模型和AIGC技术的发展&#xff0c;可以用“日新月异”来形容&#xff0c;其迭代速度史无前例&#xff0c;涌现出的各类垂直应用模型&#xff0c;也使得音视频行业的应用场景更加广泛和多样化。 然而&#xff…

如何从零开始拆解uni-app开发的vue项目(三)

前言:前两篇文章我们讲解了如何拆解uni-app开发的项目结构、实现前台数据的动态加载,今天讲一篇如何实现动态加载功能列表,以及美化界面。话不多说,直接先看源码: 在用户成功登录后,会跳转到menu.vue菜单, 再次点击点检功能时,会进入点检的具体功能跳转菜单,我们的点…

在Linux/Debian/Ubuntu上通过 Azure Data Studio 管理 SQL Server 2019

Microsoft 提供 Azure Data Studio&#xff0c;这是一种可在 Linux、macOS 和 Windows 上运行的跨平台数据库工具。 它提供与 SSMS 类似的功能&#xff0c;包括查询、脚本编写和可视化数据。 要在 Ubuntu 上安装 Azure Data Studio&#xff0c;可以按照以下步骤操作&#xff1…

Sphinx + Readthedocs 避坑速通指南

博主在学习使用 Sphinx 和 Read the docs 的过程中&#xff0c; 碰到了许多奇葩的 bug, 使得很简单的任务花费了很长的时间才解决&#xff0c;现在在这里做一个分享&#xff0c;帮助大家用更少的时间高效上线文档的内容。 总的来说&#xff0c; 任务分为两个部分&#xff1a; …

UE5制作推箱子动作时获取物体与角色朝向的角度及跨蓝图修改变量

就是脑残死磕&#xff0c;你们如果有更好的方法一定要留言啊~~独乐乐不如众乐乐。 做推箱子的时候需要考虑脸是不是面对着箱子&#xff0c;不是必须90度&#xff0c;可以有一个-45~45度的范围。 摸索了一下&#xff0c;有几种做法和几个小白坑&#xff0c;这里列出来。 一、准…

mysql 索引原理为什么用b+树而不用二叉树

在数据库中&#xff0c;索引是一种数据结构&#xff0c;它能够快速定位到存储在数据库表中特定行的数据。MySQL等数据库管理系统通常使用B树作为索引的数据结构&#xff0c;而不使用二叉树&#xff0c;主要基于以下几个原因&#xff1a; 高度平衡&#xff1a;B树是一种多路搜索…

软件推荐 篇三十七:开源免费无广告的在线音乐免费播放 | MusicFree纯净无广告体验-小众冷门推荐

引言 自从QQ音乐没了杰伦、某云开始收费&#xff0c;除了各种广告弹窗导致电脑卡的要死&#xff0c;打工人就靠这点音乐背景熬夜了&#xff0c;木有办法&#xff0c;得有个开源免费的听歌软件吧&#xff0c;一搜github&#xff0c;软件一大堆&#xff0c;作为一个打工仔&#…

【前端寻宝之路】学习和总结HTML表格的实现和合并

&#x1f308;个人主页: Aileen_0v0 &#x1f525;热门专栏: 华为鸿蒙系统学习|计算机网络|数据结构与算法|MySQL| ​&#x1f4ab;个人格言:“没有罗马,那就自己创造罗马~” #mermaid-svg-IWDj0gWiFt6IMq3x {font-family:"trebuchet ms",verdana,arial,sans-serif;f…

GraphPad Prism 10:一站式数据分析解决方案

GraphPad Prism 10是一款功能强大的数据分析和可视化软件&#xff0c;广泛应用于生命科学研究、医学、生物、化学等多个领域。以下是对其详细功能的介绍&#xff1a; 首先&#xff0c;GraphPad Prism 10具有出色的数据可视化功能。它支持各种类型的图表和图形&#xff0c;包括…

解决arco-design下拉框回显id的问题

问题描述 下拉框回显选项中没有的选项&#xff0c;就会出现以下情况&#xff0c;只能把uid回显上去 解决方案 使用ui框架自带的属性fallback-option 用法 按以上操作&#xff0c;即可解决选择框回显uid问题

论文阅读:机器人跑酷学习

项目开源地址&#xff1a;https://github.com/ZiwenZhuang/parkour 摘要&#xff1a; 跑酷对腿部机动性是一项巨大的挑战&#xff0c;要求机器人在复杂环境中快速克服各种障碍。现有方法可以生成多样化但盲目的机动技能&#xff0c;或者是基于视觉但专门化的技能&#xff0c;…

代码随想录笔记|C++数据结构与算法学习笔记-二叉树(一)|二叉树的递归遍历、二叉树的迭代遍历、二叉树的统一迭代法

全文基于代码随想录及相关讲解视频。 文字链接&#xff1a;《代码随想录》 文章目录 二叉树的递归遍历二叉树的前序遍历C代码如下 二叉树的中序遍历二叉树的后序遍历 二叉树的迭代遍历前序遍历前序遍历C代码 右序遍历右序遍历C代码 中序遍历为什么中序遍历不同中序遍历迭代法的…

FEX-Emu在Debian/Ubuntu系统使用

FEX-Emu在Debian/Ubuntu系统使用 1. Debootstrap子系统安装&#xff08;可选&#xff09;2. Debian/Ubuntu依赖包安装3. 获取FEX-Emu源码并编译4. 根文件系统RootFS安装5. 基于 FEX-Emu 运行应用 1. Debootstrap子系统安装&#xff08;可选&#xff09; sudo apt-get install …

如何让电脑定时开机?这个方法你一定要学会

前言 前段时间小白在上班的时候&#xff0c;个人使用一台台式机和一台笔记本电脑。台式机并不是经常使用&#xff0c;但整个公司的数据中心是建立在小白所使用的那台台式机上。 如果台式机没有开机&#xff0c;同事们就没办法访问数据中心获取自己想要的资料。领导也没办法链…

C#、.NET版本、Visual Studio版本对应关系及Visual Studio老版本离线包下载地址

0、写这篇文章的目的 由于电脑的环境不同&#xff0c;对于一个老电脑找到一个适配的vscode环境十分不易。总结一下C#、.NET、Visual Studio版本的对应关系&#xff0c;及各个版本Visual Studio的下载地址供大家参考 1、C#、.NET版本、Visual Studio版本对应关系如下 2、Visua…

李国武:如何评估一家精益制造咨询公司的实施能力?

在制造业转型升级的大背景下&#xff0c;精益制造已成为企业提升竞争力、实现可持续发展的关键。然而&#xff0c;面对市场上众多的精益制造咨询公司&#xff0c;如何评估其实施能力成为了众多企业的难题。本文将从多个方面为大家揭示评估精益制造咨询公司实施能力的方法&#…

MySQL数据库的索引

目录 1、索引的概念 2、索引的作用 优点 缺点 3、创建索引的原则依据 4、索引的分类和创建 ​编辑 4.1普通索引 直接创建索引 修改表方式创建索引 创建表时添加索引 删除索引 4.2唯一索引 直接创建唯一索引 修改表方式创建 创建表时指定索引 4.3主键索引&…

Lamdba表达式

Lamdba表达式 Lambda是一个匿名函数&#xff0c;我们可以将Lambda表达式理解为一段可以传递的代码&#xff08;将代码像数据一样 传递&#xff09;。使用它可以写出简洁、灵活的代码。作为一种更紧凑的代码风格&#xff0c;使java语言表达能力得到提 升。 Lambda表达式在java语…

Android Kotlin(六)协程的并发问题

书接上回&#xff1a;Android Kotlin知识汇总&#xff08;三&#xff09;Kotlin 协程 协程的并发问题 在一个协程中&#xff0c;循环创建10个子协程且单独运行各自Default线程中&#xff0c;并让每个子协程对变量 i 进行1000次自增操作。示例如下&#xff1a; fun main() …

Golang基础知识(笔记迁移)

golang 变量作用域 局部作用域&#xff1a;代码块、函数内的全局作用域&#xff1a;顶层作用域&#xff0c;代码块外的就是全局&#xff0c;如果变量名大写&#xff0c;则改变量整个程序都可以使用。 类型断言 golang的类型断言在变量后加上.(type)&#xff0c;如果类型断言…