模拟mybatis-plus使用lambda多表联查

2023-12-24 19:38

本文主要是介绍模拟mybatis-plus使用lambda多表联查,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

说明:此代码的封装并不适用于mybatis,只是模拟了mybatis-plus的LambdaQueryWrapper进行多表联查,最终生成的sql采用?号占位符,占位符的值封装在一个List<Object>中,可适用于jdbcTemplate。

        如果使用过mybatis-plus的LambdaQueryWrapper进行过查询的话,LambdaSqlBuilder的条件查询、排序、分组使用是保持一致的。

AbstractSqlBuilder是LambdaSqlBuilder 和StringSqlBuilder 的抽象父类,主要包含一些公共成员变量,and嵌套和or嵌套,嵌套用法和LambdaQueryWrapper一致

package com.zl.model.sql;import lombok.Getter;import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.function.Consumer;/*** @author zhangliang* @date 2020/7/7.*/
public abstract class AbstractSqlBuilder<C extends AbstractSqlBuilder> {/*** 占位符*/final C typedThis = ( C ) this;static final String  OR = " or ";static final String AND = " and ";String connect = AND;boolean isConnect = true;static final String ASC = "asc";static final String DESC = "desc";@Getterprotected List<Object> params = new ArrayList<>();StringBuilder sqlBd = new StringBuilder();boolean orderBy = false;boolean groupBy = false;AbstractSqlBuilder() {}public C where() {sqlBd.append(" where 1=1");return typedThis;}public abstract String sql();String in(Collection<?> list){StringBuilder builder = new StringBuilder();int size = list.size();for (int i = 0; i < size; i++) {builder.append("?,");}String str = builder.toString();return str.substring(0,str.length()-1);}public C and(Consumer<C> consumer) {isConnect = false;sqlBd.append(" and (");consumer.accept(typedThis);sqlBd.append(")");isConnect = true;return typedThis;}public C or() {connect = OR;return typedThis;}public C or(Consumer<C> consumer) {isConnect = false;sqlBd.append(" or (");consumer.accept(typedThis);sqlBd.append(")");isConnect = true;return typedThis;}public C appendSql(String sql) {sqlBd.append(sql);return typedThis;}public C unionAll(String sql) {sqlBd.append(" union all ");sqlBd.append(sql);return typedThis;}public C having(String havingSql) {sqlBd.append(" having ");sqlBd.append(havingSql);return typedThis;}
}

LambdaSqlBuilder 说明:

  • select 方法如果是同一个表的字段,可以写到一个select方法中,如果是不同表的字段,则需要再次调用select方法传入另一个表的字段,以此类推
  • selectAlias 该方法的第一个参数是要查询的字段,第二个参数是别名,多个表有字段一样的才需要起别名。默认将下划线表列转换为驼峰式的类字段名
  • from 方法默认将类名的首字母小写的驼峰表达式转为下划线作为表名,如果不符合此规则,则可调用带有表名字符串的from方法。别名默认为:表名_0,也可以传入表别名
  • 表之间连接和from表相同
  • 表字段是根据SqlFunction获取到lambda表达式所表示的字段的驼峰表达式转下划线获取到(其它不支持)
  • 排序和分组对于不同表字段也需要多次调用,和select一致

package com.zl.model.sql;import org.apache.commons.lang3.StringUtils;import java.util.*;
import java.util.function.Consumer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;/*** @author zhangliang* @date 2020/7/7.*/
public class LambdaSqlBuilder extends AbstractSqlBuilder<LambdaSqlBuilder> {/*** key class name,value alias*/private final Map<Class<?>, String> tableAliasMap = new HashMap<>(16);private final Map<Class<?>, String> tableMap = new HashMap<>(16);private final Map<String, String> tableClassNameAliasMap = new HashMap<>(16);private final Map<String, String> propertyAliasMap = new HashMap<>(16);private final List<SqlFunction<?,?>> selected = new ArrayList<>();private static Pattern humpPattern = Pattern.compile("[A-Z]");@SafeVarargspublic final <T,R>  LambdaSqlBuilder select(SqlFunction<T, R> ...columns){selected.addAll(Arrays.asList(columns));return this;}public <T,R,K,V>LambdaSqlBuilder selectAlias(SqlFunction<T,R> column,SqlFunction<K,V> alias){selected.add(column);String property = lambdaProperty(column);String className = lambdaClassName(column);String propertyAlias = lambdaProperty(alias);propertyAliasMap.put(className+"_"+property,propertyAlias);return this;}public LambdaSqlBuilder from(Class<?> table){return from(table,null);}public LambdaSqlBuilder from(Class<?> table,String alias){from(null,alias,table);return this;}public LambdaSqlBuilder from(String table,String alias,Class<?> tableClass){analysisTable(tableClass,alias,table);sqlBd.append(" from ");sqlBd.append(tableMap.get(tableClass));sqlBd.append(" ");sqlBd.append(tableAliasMap.get(tableClass));return this;}public LambdaSqlBuilder leftJoin(Class<?> table){return leftJoin(table,null);}public LambdaSqlBuilder leftJoin(Class<?> table,String alias){leftJoin(null,alias,table);return this;}public LambdaSqlBuilder leftJoin(String table,String alias,Class<?> tableClass){join(table,tableClass,alias,"left join");return this;}public LambdaSqlBuilder rightJoin(Class<?> table){return rightJoin(table,null);}public LambdaSqlBuilder rightJoin(Class<?> table,String alias){rightJoin(null,alias,table);return this;}public LambdaSqlBuilder rightJoin(String table,String alias,Class<?> tableClass){join(table,tableClass,alias,"right join");return this;}public LambdaSqlBuilder innerJoin(Class<?> table){return rightJoin(table,null);}public LambdaSqlBuilder innerJoin(Class<?> table,String alias){innerJoin(null,alias,table);return this;}public LambdaSqlBuilder innerJoin(String table,String alias,Class<?> tableClass){join(table,tableClass,alias,"inner join");return this;}private void join(String table,Class<?> tableClass,String alias,String joinType){analysisTable(tableClass,alias,table);sqlBd.append(" ");sqlBd.append(joinType);sqlBd.append(" ");sqlBd.append(tableMap.get(tableClass));sqlBd.append(" ");sqlBd.append(tableAliasMap.get(tableClass));}public <T,R,K,V>LambdaSqlBuilder on(SqlFunction<T,R> column0,SqlFunction<K,V> column1){sqlBd.append(" on ");column(column0);sqlBd.append(" = ");column(column1);return this;}public <T, R> LambdaSqlBuilder eq(SqlFunction<T, R> column, Object value) {appendWhereCondition(SymbolEnum.EQ,column,value);return this;}public <T, R> LambdaSqlBuilder ne(SqlFunction<T, R> column, Object value) {appendWhereCondition(SymbolEnum.NE,column,value);return this;}public <T, R> LambdaSqlBuilder ge(SqlFunction<T, R> column, Object value) {appendWhereCondition(SymbolEnum.GE,column,value);return this;}public <T, R> LambdaSqlBuilder gt(SqlFunction<T, R> column, Object value) {appendWhereCondition(SymbolEnum.GT,column,value);return this;}public <T, R> LambdaSqlBuilder le(SqlFunction<T, R> column, Object value) {appendWhereCondition(SymbolEnum.LE,column,value);return this;}public <T, R> LambdaSqlBuilder lt(SqlFunction<T, R> column, Object value) {appendWhereCondition(SymbolEnum.LT,column,value);return this;}public <T, R> LambdaSqlBuilder isNull(SqlFunction<T, R> column) {connectColumn(column);sqlBd.append("is Null");return this;}public <T, R> LambdaSqlBuilder isNotNull(SqlFunction<T, R> column) {connectColumn(column);sqlBd.append("is not Null");return this;}private  <T, R> void handleLike(SqlFunction<T, R> column, Object value, Consumer<LambdaSqlBuilder> consumer) {if(value != null && !"".equals(value)){connectColumn(column);sqlBd.append("like ?");consumer.accept(this);}}public <T, R> LambdaSqlBuilder like(SqlFunction<T, R> column, Object value) {handleLike(column,value,v->v.params.add("%"+value+"%"));return this;}public <T, R> LambdaSqlBuilder notLike(SqlFunction<T, R> column, Object value) {if(value != null && !"".equals(value)){connectColumn(column);sqlBd.append("not like ?");params.add("%"+value+"%");}return this;}public <T, R> LambdaSqlBuilder likeLeft(SqlFunction<T, R> column, Object value) {handleLike(column,value,v->v.params.add("%"+value));return this;}public <T, R> LambdaSqlBuilder likeRight(SqlFunction<T, R> column, Object value) {handleLike(column,value,v->v.params.add(value+"%"));return this;}public <T, R> LambdaSqlBuilder in(SqlFunction<T, R> column, Collection<?> values) {if(values != null && !values.isEmpty()){connectColumn(column);sqlBd.append("in(");sqlBd.append(in(values));sqlBd.append(")");params.addAll(values);}return this;}public <T, R> LambdaSqlBuilder notIn(SqlFunction<T, R> column, Collection<?> values) {if(values != null && !values.isEmpty()){connectColumn(column);sqlBd.append("not in(");sqlBd.append(in(values));sqlBd.append(")");params.addAll(values);}return this;}public <T, R> LambdaSqlBuilder inSql(SqlFunction<T, R> column, String inSql) {if(inSql != null && !"".equals(inSql)){connectColumn(column);sqlBd.append("in(");sqlBd.append(inSql);sqlBd.append(")");}return this;}public <T, R> LambdaSqlBuilder notInSql(SqlFunction<T, R> column, String inSql) {if(inSql != null && !"".equals(inSql)){connectColumn(column);sqlBd.append("not in(");sqlBd.append(inSql);sqlBd.append(")");}return this;}public <T, R> LambdaSqlBuilder between(SqlFunction<T, R> column, Object value1,Object value2) {if(value1 != null && !"".equals(value1) && value2 != null && !"".equals(value2)){connectColumn(column);sqlBd.append("between ? and ?");params.add(value1);params.add(value2);}return this;}public <T, R> LambdaSqlBuilder notBetween(SqlFunction<T, R> column, Object value1,Object value2) {if(value1 != null && !"".equals(value1) && value2 != null && !"".equals(value2)){connectColumn(column);sqlBd.append("not between ? and ?");params.add(value1);params.add(value2);}return this;}public <T, R> LambdaSqlBuilder orderByAsc(SqlFunction<T, R> column) {orderBy(ASC,column);return this;}@SafeVarargspublic final <T, R> LambdaSqlBuilder orderByAsc(SqlFunction<T, R> ...columns) {orderBy(ASC,columns);return this;}@SafeVarargsprivate final <T, R> void orderBy(String dir,SqlFunction<T, R> ...columns) {if(!orderBy){sqlBd.append(" order by ");}for (SqlFunction<T, R> column : columns) {if(orderBy){sqlBd.append(", ");}orderBy = true;column(column);if(DESC.equals(dir)){sqlBd.append(" desc");}}}public <T, R> LambdaSqlBuilder orderByDesc(SqlFunction<T, R> column) {orderBy(DESC,column);return this;}@SafeVarargspublic final <T, R> LambdaSqlBuilder orderByDesc(SqlFunction<T, R> ...columns) {orderBy(DESC,columns);return this;}public <T, R> LambdaSqlBuilder groupBy(SqlFunction<T, R> column) {groupBy(groupBy,column);return this;}@SafeVarargspublic final <T, R> LambdaSqlBuilder groupBy(SqlFunction<T, R>... columns) {groupBy(groupBy,columns);return this;}@SafeVarargsprivate final <T, R> void groupBy(boolean hadGroupBy,SqlFunction<T, R> ...columns) {if(!hadGroupBy){sqlBd.append(" group by ");}for (SqlFunction<T, R> column : columns) {if(hadGroupBy){sqlBd.append(", ");}hadGroupBy = true;groupBy = true;column(column);}}@Overridepublic String sql() {StringBuilder select = getSelect();return select.append(sqlBd).toString().replace(" 1=1 and", "").replace(" or ()","").replace(" and ()","");}private StringBuilder getSelect(){StringBuilder select = new StringBuilder("select ");String humpToLine;String alias;String property;String className;int size = selected.size();for (SqlFunction<?, ?> column : selected) {className = lambdaClassName(column);property = lambdaProperty(column);humpToLine = lambdaPropertyForHumpToLine(column);select.append(tableClassNameAliasMap.get(className));select.append(".");select.append(humpToLine);alias = propertyAliasMap.get(className+"_"+property);if (alias != null) {select.append(" as " );select.append(alias);} else {if (!humpToLine.equals(property)) {select.append(" as " );select.append(property);}}if(size != 1){select.append(",");}size--;}return select;}/** 驼峰转下划线*/private String humpToLine(String str) {Matcher matcher = humpPattern.matcher(str);StringBuffer sb = new StringBuffer();while (matcher.find()) {matcher.appendReplacement(sb, "_" + matcher.group(0).toLowerCase());}matcher.appendTail(sb);return sb.toString();}private String lambdaProperty(SqlFunction<?,?> func){String implMethodName = func.getImplMethodName();String name = implMethodName.substring(3);return name.substring(0, 1).toLowerCase(Locale.ENGLISH) + name.substring(1);}private String lambdaPropertyForHumpToLine(SqlFunction<?,?> func){String implMethodName = func.getImplMethodName();String name = implMethodName.substring(3);return humpToLine(name.substring(0, 1).toLowerCase(Locale.ENGLISH) + name.substring(1));}private String lambdaClassName(SqlFunction<?,?> func){String implClass = func.getImplClass();return implClass.substring(implClass.lastIndexOf('/')+1);}private void analysisTable(Class<?> tableClass,String alias,String table){String name = tableClass.getSimpleName();if (StringUtils.isBlank(table)) {table = humpToLine(name.substring(0, 1).toLowerCase(Locale.ENGLISH) + name.substring(1));}tableMap.put(tableClass,table);if (StringUtils.isBlank(alias)) {tableAliasMap.put(tableClass,table+"_0");tableClassNameAliasMap.put(name,table+"_0");}else {tableAliasMap.put(tableClass,alias);tableClassNameAliasMap.put(name,alias);}}private <T, R> void appendWhereCondition(SymbolEnum symbol, SqlFunction<T, R> column, Object value){if(value != null && !"".equals(value)){connectColumn(column);sqlBd.append(symbol.getName());sqlBd.append(" ?");params.add(value);}}public <T, R> void connectColumn(SqlFunction<T, R> column) {if (isConnect) {sqlBd.append(connect);}else {isConnect = true;}column(column);sqlBd.append(" ");if (connect.equals(OR)) {connect = AND;}}private <T, R>void column(SqlFunction<T, R> column){sqlBd.append(tableClassNameAliasMap.get(lambdaClassName(column)));sqlBd.append(".");sqlBd.append(lambdaPropertyForHumpToLine(column));}}

SqlFunction: 从lambda获取字段名和类名

package com.zl.model.sql;import java.io.Serializable;
import java.lang.invoke.SerializedLambda;
import java.lang.reflect.Method;
import java.util.function.Function;@FunctionalInterface
public interface SqlFunction<T, R> extends Function<T, R>, Serializable {default SerializedLambda getSerializedLambda(){Method write;try {write = this.getClass().getDeclaredMethod("writeReplace");write.setAccessible(true);return (SerializedLambda) write.invoke(this);} catch (Exception e) {throw new IllegalArgumentException();}}default String getImplClass() {return getSerializedLambda().getImplClass();}default String getImplMethodName() {return getSerializedLambda().getImplMethodName();}
}

StringSqlBuilder说明:

  • select 不支持多次调用
  • orderBy 不支持多次调用,且需要传入排序方向
  • groupBy 不支持多次调用
  • 调用方式表名和字段名都传入字符串,调用链和LambdaSqlBuilder 一样
package com.zl.model.sql;import java.util.Collection;
import java.util.function.Consumer;/*** @author zhangliang* @date 2020/7/7.*/
public class StringSqlBuilder extends AbstractSqlBuilder<StringSqlBuilder> {public StringSqlBuilder select(String select){sqlBd.append("select ");sqlBd.append(select);return typedThis;}public StringSqlBuilder from(String table){sqlBd.append(" from ");sqlBd.append(table);return typedThis;}public StringSqlBuilder leftJoin(String table){sqlBd.append(" left join ");sqlBd.append(table);return typedThis;}public StringSqlBuilder rightJoin(String table){sqlBd.append(" right join ");sqlBd.append(table);return typedThis;}public StringSqlBuilder innerJoin(String table){sqlBd.append(" inner join ");sqlBd.append(table);return typedThis;}public StringSqlBuilder on(String column0,String column1){sqlBd.append(" on ");sqlBd.append(column0);sqlBd.append(" = ");sqlBd.append(column1);return typedThis;}public StringSqlBuilder orderBy(String orderBy) {sqlBd.append(" order by " );sqlBd.append(orderBy);return typedThis;}public StringSqlBuilder groupBy(String groupBy){sqlBd.append(" group by ");sqlBd.append(groupBy);return typedThis;}public StringSqlBuilder eq(String column, Object value) {appendWhereCondition(SymbolEnum.EQ,column,value);return this;}public StringSqlBuilder ne(String column, Object value) {appendWhereCondition(SymbolEnum.NE,column,value);return this;}public StringSqlBuilder ge(String column, Object value) {appendWhereCondition(SymbolEnum.GE,column,value);return this;}public StringSqlBuilder gt(String column, Object value) {appendWhereCondition(SymbolEnum.GT,column,value);return this;}public StringSqlBuilder le(String column, Object value) {appendWhereCondition(SymbolEnum.LE,column,value);return this;}public StringSqlBuilder lt(String column, Object value) {appendWhereCondition(SymbolEnum.LT,column,value);return this;}public StringSqlBuilder isNull(String column) {connectColumn(column);sqlBd.append("is Null");return this;}public StringSqlBuilder isNotNull(String column) {connectColumn(column);sqlBd.append("is not Null");return this;}private  void handleLike(String column, Object value, Consumer<StringSqlBuilder> consumer) {if(value != null && !"".equals(value)){connectColumn(column);sqlBd.append("like ?");consumer.accept(this);}}public StringSqlBuilder like(String column, Object value) {handleLike(column,value,v->v.params.add("%"+value+"%"));return this;}public StringSqlBuilder notLike(String column, Object value) {if(value != null && !"".equals(value)){connectColumn(column);sqlBd.append("not like ?");params.add("%"+value+"%");}return this;}public StringSqlBuilder likeLeft(String column, Object value) {handleLike(column,value,v->v.params.add("%"+value));return this;}public StringSqlBuilder likeRight(String column, Object value) {handleLike(column,value,v->v.params.add(value+"%"));return this;}public StringSqlBuilder in(String column, Collection<?> values) {handleIn(column,values,"in");return this;}public StringSqlBuilder notIn(String column, Collection<?> values) {handleIn(column,values,"not in");return this;}private void handleIn(String column, Collection<?> values,String in) {if(values != null && !values.isEmpty()){connectColumn(column);sqlBd.append(in);sqlBd.append("(");sqlBd.append(in(values));sqlBd.append(")");params.addAll(values);}}public StringSqlBuilder inSql(String column, String inSql) {if(inSql != null && !"".equals(inSql)){connectColumn(column);sqlBd.append("in(");sqlBd.append(inSql);sqlBd.append(")");}return this;}public StringSqlBuilder notInSql(String column, String inSql) {if(inSql != null && !"".equals(inSql)){connectColumn(column);sqlBd.append("not in(");sqlBd.append(inSql);sqlBd.append(")");}return this;}public StringSqlBuilder between(String column, Object value1,Object value2) {handleBetween(column,value1,value2,"between");return this;}public StringSqlBuilder notBetween(String column, Object value1,Object value2) {handleBetween(column,value1,value2,"not between");return this;}private void handleBetween(String column, Object value1,Object value2,String between){if(value1 != null && !"".equals(value1) && value2 != null && !"".equals(value2)){connectColumn(column);sqlBd.append(between);sqlBd.append(" ? and ?");params.add(value1);params.add(value2);}}@Overridepublic String sql() {return sqlBd.toString().replace(" 1=1 and", "").replace(" or ()","").replace(" and ()","");}private void appendWhereCondition(SymbolEnum symbol, String column, Object value){if(value != null && !"".equals(value)){connectColumn(column);sqlBd.append(symbol.getName());sqlBd.append(" ?");params.add(value);}}private void connectColumn(String column) {if (isConnect) {sqlBd.append(connect);}else {isConnect = true;}sqlBd.append(column);sqlBd.append(" ");if (connect.equals(OR)) {connect = AND;}}
}
package com.zl.model.sql;import lombok.Getter;/*** @author zhangliang* @date 2020/7/7.*/
@Getter
public enum SymbolEnum {EQ("="),NE("!="),GE(">="),GT(">"),LE("<="),LT("<");private String name;SymbolEnum(String name){this.name = name;}
}

测试类:LambdaSqlBuilder 和StringSqlBuilder对于构建相同sql示例

package com.zl.model.sql;import com.zl.domain.Coder;
import com.zl.domain.Company;import java.util.Arrays;/*** @author zhangliang* @date 2020/7/9.*/
public class TestSqlBuilder {public static void main(String[] args) {LambdaSqlBuilder builder = new LambdaSqlBuilder();System.out.println(builder.select(Coder::getName,Coder::getAge).selectAlias(Company::getName,Company::getId).from(Coder.class,"c").leftJoin(Company.class, "co").on(Coder::getCompanyId, Company::getId).where().eq(Coder::getName, "123").and(v -> v.le(Coder::getName, "123").lt(Coder::getName, "123")).or(v -> v.ge(Coder::getName, "123").or().gt(Coder::getName, "123")).or(v -> v.ne(Coder::getName, null)).like(Coder::getName, "12").isNotNull(Coder::getName).isNull(Coder::getName).between(Coder::getId,1,2).in(Coder::getId, Arrays.asList(1L,2L)).inSql(Coder::getId,"select id from coder").orderByAsc(Company::getId, Company::getName).orderByAsc(Coder::getName).orderByDesc(Coder::getId, Coder::getAge).groupBy(Company::getId, Company::getName).groupBy(Coder::getName).sql());StringSqlBuilder builder1 = new StringSqlBuilder();System.out.println(builder1.select("c.name,c.age,co.name as id").from("coder c").leftJoin("company co").on("c.company_id","co.id").where().eq("c.name", "123").and(v -> v.le("c.name", "123").lt("c.name", "123")).or(v -> v.ge("c.name", "123").or().gt("c.name", "123")).or(v -> v.ne("c.name", null)).like("c.name", "12").isNotNull("c.name").isNull("c.name").between("c.id",1,2).in("c.id", Arrays.asList(1L,2L)).inSql("c.id","select id from coder").orderBy("co.id, co.name, c.name, c.id desc, c.age desc").groupBy("co.id, co.name, c.name").sql());}
}

结果:

select c.name,c.age,co.name as id from coder c left join company co on c.company_id = co.id where c.name = ? and (c.name <= ? and c.name < ?) or (c.name >= ? or c.name > ?) and c.name like ? and c.name is not Null and c.name is Null and c.id between ? and ? and c.id in(?,?) and c.id in(select id from coder) order by co.id, co.name, c.name, c.id desc, c.age desc group by co.id, co.name, c.nameselect c.name,c.age,co.name as id from coder c left join company co on c.company_id = co.id where c.name = ? and (c.name <= ? and c.name < ?) or (c.name >= ? or c.name > ?) and c.name like ? and c.name is not Null and c.name is Null and c.id between ? and ? and c.id in(?,?) and c.id in(select id from coder) order by co.id, co.name, c.name, c.id desc, c.age desc group by co.id, co.name, c.name

这篇关于模拟mybatis-plus使用lambda多表联查的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/532903

相关文章

使用Python创建一个功能完整的Windows风格计算器程序

《使用Python创建一个功能完整的Windows风格计算器程序》:本文主要介绍如何使用Python和Tkinter创建一个功能完整的Windows风格计算器程序,包括基本运算、高级科学计算(如三... 目录python实现Windows系统计算器程序(含高级功能)1. 使用Tkinter实现基础计算器2.

在.NET平台使用C#为PDF添加各种类型的表单域的方法

《在.NET平台使用C#为PDF添加各种类型的表单域的方法》在日常办公系统开发中,涉及PDF处理相关的开发时,生成可填写的PDF表单是一种常见需求,与静态PDF不同,带有**表单域的文档支持用户直接在... 目录引言使用 PdfTextBoxField 添加文本输入域使用 PdfComboBoxField

慢sql提前分析预警和动态sql替换-Mybatis-SQL

《慢sql提前分析预警和动态sql替换-Mybatis-SQL》为防止慢SQL问题而开发的MyBatis组件,该组件能够在开发、测试阶段自动分析SQL语句,并在出现慢SQL问题时通过Ducc配置实现动... 目录背景解决思路开源方案调研设计方案详细设计使用方法1、引入依赖jar包2、配置组件XML3、核心配

Git可视化管理工具(SourceTree)使用操作大全经典

《Git可视化管理工具(SourceTree)使用操作大全经典》本文详细介绍了SourceTree作为Git可视化管理工具的常用操作,包括连接远程仓库、添加SSH密钥、克隆仓库、设置默认项目目录、代码... 目录前言:连接Gitee or github,获取代码:在SourceTree中添加SSH密钥:Cl

Python中模块graphviz使用入门

《Python中模块graphviz使用入门》graphviz是一个用于创建和操作图形的Python库,本文主要介绍了Python中模块graphviz使用入门,具有一定的参考价值,感兴趣的可以了解一... 目录1.安装2. 基本用法2.1 输出图像格式2.2 图像style设置2.3 属性2.4 子图和聚

windows和Linux使用命令行计算文件的MD5值

《windows和Linux使用命令行计算文件的MD5值》在Windows和Linux系统中,您可以使用命令行(终端或命令提示符)来计算文件的MD5值,文章介绍了在Windows和Linux/macO... 目录在Windows上:在linux或MACOS上:总结在Windows上:可以使用certuti

CentOS和Ubuntu系统使用shell脚本创建用户和设置密码

《CentOS和Ubuntu系统使用shell脚本创建用户和设置密码》在Linux系统中,你可以使用useradd命令来创建新用户,使用echo和chpasswd命令来设置密码,本文写了一个shell... 在linux系统中,你可以使用useradd命令来创建新用户,使用echo和chpasswd命令来设

Python使用Matplotlib绘制3D曲面图详解

《Python使用Matplotlib绘制3D曲面图详解》:本文主要介绍Python使用Matplotlib绘制3D曲面图,在Python中,使用Matplotlib库绘制3D曲面图可以通过mpl... 目录准备工作绘制简单的 3D 曲面图绘制 3D 曲面图添加线框和透明度控制图形视角Matplotlib

Pandas中统计汇总可视化函数plot()的使用

《Pandas中统计汇总可视化函数plot()的使用》Pandas提供了许多强大的数据处理和分析功能,其中plot()函数就是其可视化功能的一个重要组成部分,本文主要介绍了Pandas中统计汇总可视化... 目录一、plot()函数简介二、plot()函数的基本用法三、plot()函数的参数详解四、使用pl

MySQL 多表连接操作方法(INNER JOIN、LEFT JOIN、RIGHT JOIN、FULL OUTER JOIN)

《MySQL多表连接操作方法(INNERJOIN、LEFTJOIN、RIGHTJOIN、FULLOUTERJOIN)》多表连接是一种将两个或多个表中的数据组合在一起的SQL操作,通过连接,... 目录一、 什么是多表连接?二、 mysql 支持的连接类型三、 多表连接的语法四、实战示例 数据准备五、连接的性