模拟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

相关文章

Java中流式并行操作parallelStream的原理和使用方法

《Java中流式并行操作parallelStream的原理和使用方法》本文详细介绍了Java中的并行流(parallelStream)的原理、正确使用方法以及在实际业务中的应用案例,并指出在使用并行流... 目录Java中流式并行操作parallelStream0. 问题的产生1. 什么是parallelS

Linux join命令的使用及说明

《Linuxjoin命令的使用及说明》`join`命令用于在Linux中按字段将两个文件进行连接,类似于SQL的JOIN,它需要两个文件按用于匹配的字段排序,并且第一个文件的换行符必须是LF,`jo... 目录一. 基本语法二. 数据准备三. 指定文件的连接key四.-a输出指定文件的所有行五.-o指定输出

Linux jq命令的使用解读

《Linuxjq命令的使用解读》jq是一个强大的命令行工具,用于处理JSON数据,它可以用来查看、过滤、修改、格式化JSON数据,通过使用各种选项和过滤器,可以实现复杂的JSON处理任务... 目录一. 简介二. 选项2.1.2.2-c2.3-r2.4-R三. 字段提取3.1 普通字段3.2 数组字段四.

Linux kill正在执行的后台任务 kill进程组使用详解

《Linuxkill正在执行的后台任务kill进程组使用详解》文章介绍了两个脚本的功能和区别,以及执行这些脚本时遇到的进程管理问题,通过查看进程树、使用`kill`命令和`lsof`命令,分析了子... 目录零. 用到的命令一. 待执行的脚本二. 执行含子进程的脚本,并kill2.1 进程查看2.2 遇到的

MyBatis常用XML语法详解

《MyBatis常用XML语法详解》文章介绍了MyBatis常用XML语法,包括结果映射、查询语句、插入语句、更新语句、删除语句、动态SQL标签以及ehcache.xml文件的使用,感兴趣的朋友跟随小... 目录1、定义结果映射2、查询语句3、插入语句4、更新语句5、删除语句6、动态 SQL 标签7、ehc

详解SpringBoot+Ehcache使用示例

《详解SpringBoot+Ehcache使用示例》本文介绍了SpringBoot中配置Ehcache、自定义get/set方式,并实际使用缓存的过程,文中通过示例代码介绍的非常详细,对大家的学习或者... 目录摘要概念内存与磁盘持久化存储:配置灵活性:编码示例引入依赖:配置ehcache.XML文件:配置

Java 虚拟线程的创建与使用深度解析

《Java虚拟线程的创建与使用深度解析》虚拟线程是Java19中以预览特性形式引入,Java21起正式发布的轻量级线程,本文给大家介绍Java虚拟线程的创建与使用,感兴趣的朋友一起看看吧... 目录一、虚拟线程简介1.1 什么是虚拟线程?1.2 为什么需要虚拟线程?二、虚拟线程与平台线程对比代码对比示例:三

k8s按需创建PV和使用PVC详解

《k8s按需创建PV和使用PVC详解》Kubernetes中,PV和PVC用于管理持久存储,StorageClass实现动态PV分配,PVC声明存储需求并绑定PV,通过kubectl验证状态,注意回收... 目录1.按需创建 PV(使用 StorageClass)创建 StorageClass2.创建 PV

Redis 基本数据类型和使用详解

《Redis基本数据类型和使用详解》String是Redis最基本的数据类型,一个键对应一个值,它的功能十分强大,可以存储字符串、整数、浮点数等多种数据格式,本文给大家介绍Redis基本数据类型和... 目录一、Redis 入门介绍二、Redis 的五大基本数据类型2.1 String 类型2.2 Hash

MyBatis延迟加载与多级缓存全解析

《MyBatis延迟加载与多级缓存全解析》文章介绍MyBatis的延迟加载与多级缓存机制,延迟加载按需加载关联数据提升性能,一级缓存会话级默认开启,二级缓存工厂级支持跨会话共享,增删改操作会清空对应缓... 目录MyBATis延迟加载策略一对多示例一对多示例MyBatis框架的缓存一级缓存二级缓存MyBat