模拟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使用FastAPI实现大文件分片上传与断点续传功能

《Python使用FastAPI实现大文件分片上传与断点续传功能》大文件直传常遇到超时、网络抖动失败、失败后只能重传的问题,分片上传+断点续传可以把大文件拆成若干小块逐个上传,并在中断后从已完成分片继... 目录一、接口设计二、服务端实现(FastAPI)2.1 运行环境2.2 目录结构建议2.3 serv

MyBatis分页查询实战案例完整流程

《MyBatis分页查询实战案例完整流程》MyBatis是一个强大的Java持久层框架,支持自定义SQL和高级映射,本案例以员工工资信息管理为例,详细讲解如何在IDEA中使用MyBatis结合Page... 目录1. MyBATis框架简介2. 分页查询原理与应用场景2.1 分页查询的基本原理2.1.1 分

Spring Security简介、使用与最佳实践

《SpringSecurity简介、使用与最佳实践》SpringSecurity是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架,本文给大家介绍SpringSec... 目录一、如何理解 Spring Security?—— 核心思想二、如何在 Java 项目中使用?——

springboot中使用okhttp3的小结

《springboot中使用okhttp3的小结》OkHttp3是一个JavaHTTP客户端,可以处理各种请求类型,比如GET、POST、PUT等,并且支持高效的HTTP连接池、请求和响应缓存、以及异... 在 Spring Boot 项目中使用 OkHttp3 进行 HTTP 请求是一个高效且流行的方式。

MyBatis Plus实现时间字段自动填充的完整方案

《MyBatisPlus实现时间字段自动填充的完整方案》在日常开发中,我们经常需要记录数据的创建时间和更新时间,传统的做法是在每次插入或更新操作时手动设置这些时间字段,这种方式不仅繁琐,还容易遗漏,... 目录前言解决目标技术栈实现步骤1. 实体类注解配置2. 创建元数据处理器3. 服务层代码优化填充机制详

mybatis映射器配置小结

《mybatis映射器配置小结》本文详解MyBatis映射器配置,重点讲解字段映射的三种解决方案(别名、自动驼峰映射、resultMap),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定... 目录select中字段的映射问题使用SQL语句中的别名功能使用mapUnderscoreToCame

Java使用Javassist动态生成HelloWorld类

《Java使用Javassist动态生成HelloWorld类》Javassist是一个非常强大的字节码操作和定义库,它允许开发者在运行时创建新的类或者修改现有的类,本文将简单介绍如何使用Javass... 目录1. Javassist简介2. 环境准备3. 动态生成HelloWorld类3.1 创建CtC

使用Python批量将.ncm格式的音频文件转换为.mp3格式的实战详解

《使用Python批量将.ncm格式的音频文件转换为.mp3格式的实战详解》本文详细介绍了如何使用Python通过ncmdump工具批量将.ncm音频转换为.mp3的步骤,包括安装、配置ffmpeg环... 目录1. 前言2. 安装 ncmdump3. 实现 .ncm 转 .mp34. 执行过程5. 执行结

Java使用jar命令配置服务器端口的完整指南

《Java使用jar命令配置服务器端口的完整指南》本文将详细介绍如何使用java-jar命令启动应用,并重点讲解如何配置服务器端口,同时提供一个实用的Web工具来简化这一过程,希望对大家有所帮助... 目录1. Java Jar文件简介1.1 什么是Jar文件1.2 创建可执行Jar文件2. 使用java

C#使用Spire.Doc for .NET实现HTML转Word的高效方案

《C#使用Spire.Docfor.NET实现HTML转Word的高效方案》在Web开发中,HTML内容的生成与处理是高频需求,然而,当用户需要将HTML页面或动态生成的HTML字符串转换为Wor... 目录引言一、html转Word的典型场景与挑战二、用 Spire.Doc 实现 HTML 转 Word1