From bb6549ebfcd6f96a41365077f7d00e8ec504c9fa Mon Sep 17 00:00:00 2001 From: leheyue Date: Thu, 21 Sep 2023 14:30:46 +0800 Subject: [PATCH 1/4] =?UTF-8?q?db=E6=A8=A1=E5=9D=97=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E8=A1=A8=E8=BF=9E=E6=8E=A5=E6=8E=A5=E5=8F=A3=E5=92=8C=E6=98=A0?= =?UTF-8?q?=E5=B0=84=E5=AD=97=E6=AE=B5=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../core/interceptor/ResultProvider.java | 2 +- .../magicapi/modules/db/SQLModule.java | 14 +- .../provider/PascalColumnMapperProvider.java | 4 +- .../magicapi/modules/db/table/DbConstant.java | 38 + .../modules/db/table/JoinInterface.java | 56 ++ .../modules/db/table/JoinedTable.java | 39 ++ .../magicapi/modules/db/table/NamedTable.java | 310 +++++---- .../magicapi/modules/db/table/On.java | 532 ++++++++++++++ .../magicapi/modules/db/table/TableBase.java | 177 +++++ .../modules/db/table/TableInterface.java | 75 ++ .../magicapi/modules/db/table/Where.java | 501 +++++++------ .../magicapi/modules/db/table/WhereBase.java | 658 ++++++++++++++++++ 12 files changed, 2072 insertions(+), 334 deletions(-) create mode 100644 magic-api/src/main/java/org/ssssssss/magicapi/modules/db/table/DbConstant.java create mode 100644 magic-api/src/main/java/org/ssssssss/magicapi/modules/db/table/JoinInterface.java create mode 100644 magic-api/src/main/java/org/ssssssss/magicapi/modules/db/table/JoinedTable.java create mode 100644 magic-api/src/main/java/org/ssssssss/magicapi/modules/db/table/On.java create mode 100644 magic-api/src/main/java/org/ssssssss/magicapi/modules/db/table/TableBase.java create mode 100644 magic-api/src/main/java/org/ssssssss/magicapi/modules/db/table/TableInterface.java create mode 100644 magic-api/src/main/java/org/ssssssss/magicapi/modules/db/table/WhereBase.java diff --git a/magic-api/src/main/java/org/ssssssss/magicapi/core/interceptor/ResultProvider.java b/magic-api/src/main/java/org/ssssssss/magicapi/core/interceptor/ResultProvider.java index 905d4fef..da3be5a6 100644 --- a/magic-api/src/main/java/org/ssssssss/magicapi/core/interceptor/ResultProvider.java +++ b/magic-api/src/main/java/org/ssssssss/magicapi/core/interceptor/ResultProvider.java @@ -105,7 +105,7 @@ public interface ResultProvider { * @param total 总数 * @param data 数据内容 */ - default Object buildPageResult(RequestEntity requestEntity, Page page, long total, List> data) { + default PageResult buildPageResult(RequestEntity requestEntity, Page page, long total, List> data) { return new PageResult<>(total, data); } diff --git a/magic-api/src/main/java/org/ssssssss/magicapi/modules/db/SQLModule.java b/magic-api/src/main/java/org/ssssssss/magicapi/modules/db/SQLModule.java index 4ee5cc0b..04b9d57f 100644 --- a/magic-api/src/main/java/org/ssssssss/magicapi/modules/db/SQLModule.java +++ b/magic-api/src/main/java/org/ssssssss/magicapi/modules/db/SQLModule.java @@ -17,6 +17,7 @@ import org.ssssssss.magicapi.modules.db.dialect.DialectAdapter; import org.ssssssss.magicapi.modules.db.inteceptor.NamedTableInterceptor; import org.ssssssss.magicapi.modules.db.inteceptor.SQLInterceptor; import org.ssssssss.magicapi.modules.db.model.Page; +import org.ssssssss.magicapi.modules.db.model.PageResult; import org.ssssssss.magicapi.modules.db.model.SqlTypes; import org.ssssssss.magicapi.modules.db.provider.PageProvider; import org.ssssssss.magicapi.modules.db.table.NamedTable; @@ -550,7 +551,7 @@ public class SQLModule implements DynamicAttribute, Dynami } @Transient - public Object page(BoundSql boundSql) { + public PageResult page(BoundSql boundSql) { Page page = pageProvider.getPage(boundSql.getRuntimeContext()); return page(boundSql, page); } @@ -598,7 +599,7 @@ public class SQLModule implements DynamicAttribute, Dynami return page(count, boundSql, new Page(limit, offset), null); } - private Object page(int count, BoundSql boundSql, Page page, Dialect dialect) { + private PageResult page(int count, BoundSql boundSql, Page page, Dialect dialect) { List> list = null; if (count > 0) { if (dialect == null) { @@ -612,7 +613,7 @@ public class SQLModule implements DynamicAttribute, Dynami } @Transient - public Object page(BoundSql boundSql, Page page) { + public PageResult page(BoundSql boundSql, Page page) { assertDatasourceNotNull(); Dialect dialect = dataSourceNode.getDialect(dialectAdapter); BoundSql countBoundSql = boundSql.copy(dialect.getCountSql(boundSql.getSql())); @@ -721,7 +722,12 @@ public class SQLModule implements DynamicAttribute, Dynami @Comment("指定table,进行单表操作") public NamedTable table(@Comment(name = "tableName", value = "表名") String tableName) { - return new NamedTable(tableName, this, rowMapColumnMapper, namedTableInterceptors); + return new NamedTable(tableName, null, this, rowMapColumnMapper, namedTableInterceptors); + } + + @Comment("指定table,进行单表操作") + public NamedTable table(@Comment(name = "tableName", value = "表名") String tableName, @Comment(name = "alias", value = "别名") String alias) { + return new NamedTable(tableName, alias, this, rowMapColumnMapper, namedTableInterceptors); } private BoundSql buildPageBoundSql(Dialect dialect, BoundSql boundSql, long offset, long limit) { diff --git a/magic-api/src/main/java/org/ssssssss/magicapi/modules/db/provider/PascalColumnMapperProvider.java b/magic-api/src/main/java/org/ssssssss/magicapi/modules/db/provider/PascalColumnMapperProvider.java index 76193d03..d34effb4 100644 --- a/magic-api/src/main/java/org/ssssssss/magicapi/modules/db/provider/PascalColumnMapperProvider.java +++ b/magic-api/src/main/java/org/ssssssss/magicapi/modules/db/provider/PascalColumnMapperProvider.java @@ -37,12 +37,14 @@ public class PascalColumnMapperProvider implements ColumnMapperProvider { @Override public String unmapping(String name) { StringBuilder sb = new StringBuilder(); + boolean isFirst = true; for (int i = 0; i < name.length(); i++) { char ch = name.charAt(i); - if (i > 0 && Character.isUpperCase(ch)) { + if (!isFirst && Character.isUpperCase(ch)) { sb.append("_"); } sb.append(Character.toLowerCase(ch)); + isFirst = (ch == '.' || ch == ' '); } return sb.toString(); } diff --git a/magic-api/src/main/java/org/ssssssss/magicapi/modules/db/table/DbConstant.java b/magic-api/src/main/java/org/ssssssss/magicapi/modules/db/table/DbConstant.java new file mode 100644 index 00000000..f274d72c --- /dev/null +++ b/magic-api/src/main/java/org/ssssssss/magicapi/modules/db/table/DbConstant.java @@ -0,0 +1,38 @@ +package org.ssssssss.magicapi.modules.db.table; + +/** + * 数据库操作常量 + * @author tangchen + */ +public interface DbConstant { + + String AS = " AS "; + + String JOIN = "JOIN"; + + String LEFT = "LEFT"; + + String RIGHT = "RIGHT"; + + String INNER = "INNER"; + + String SPACE = " "; + + String DOT = "."; + + + /** + * " LEFT JOIN " + */ + String LEFT_JOIN = SPACE + LEFT + SPACE + JOIN + SPACE; + + /** + * " RIGHT JOIN " + */ + String RIGHT_JOIN = SPACE + RIGHT + SPACE + JOIN + SPACE; + + /** + * " INNER JOIN " + */ + String INNER_JOIN = SPACE + INNER + SPACE + JOIN + SPACE; +} diff --git a/magic-api/src/main/java/org/ssssssss/magicapi/modules/db/table/JoinInterface.java b/magic-api/src/main/java/org/ssssssss/magicapi/modules/db/table/JoinInterface.java new file mode 100644 index 00000000..73b2b66d --- /dev/null +++ b/magic-api/src/main/java/org/ssssssss/magicapi/modules/db/table/JoinInterface.java @@ -0,0 +1,56 @@ +package org.ssssssss.magicapi.modules.db.table; + +import org.ssssssss.script.annotation.Comment; + +import java.beans.Transient; + +/** + * 关联表操作接口 + * + * @author tom + */ +public interface JoinInterface { + + @Transient + @Comment("拼接join") + JoinedTable join(boolean condition, String joinType, String tableName, String alias); + + @Comment("拼接innerJoin") + default JoinedTable innerJoin(@Comment(name = "condition", value = "判断表达式,当为true时拼接条件") boolean condition, + @Comment(name = "tableName", value = "表名") String tableName, + @Comment(name = "alias", value = "别名") String alias) { + return join(condition, DbConstant.INNER_JOIN, tableName, alias); + } + + @Comment("拼接innerJoin") + default JoinedTable innerJoin(@Comment(name = "tableName", value = "表名") String tableName, + @Comment(name = "alias", value = "别名") String alias) { + return join(true, DbConstant.INNER_JOIN, tableName, alias); + } + + @Comment("拼接leftJoin") + default JoinedTable leftJoin(@Comment(name = "condition", value = "判断表达式,当为true时拼接条件") boolean condition, + @Comment(name = "tableName", value = "表名") String tableName, + @Comment(name = "alias", value = "别名") String alias) { + return join(condition, DbConstant.LEFT_JOIN, tableName, alias); + } + + @Comment("拼接leftJoin") + default JoinedTable leftJoin(@Comment(name = "tableName", value = "表名") String tableName, + @Comment(name = "alias", value = "别名") String alias) { + return join(true, DbConstant.LEFT_JOIN, tableName, alias); + } + + @Comment("拼接rightJoin") + default JoinedTable rightJoin(@Comment(name = "condition", value = "判断表达式,当为true时拼接条件") boolean condition, + @Comment(name = "tableName", value = "表名") String tableName, + @Comment(name = "alias", value = "别名") String alias) { + return join(condition, DbConstant.RIGHT_JOIN, tableName, alias); + } + + @Comment("拼接rightJoin") + default JoinedTable rightJoin(@Comment(name = "tableName", value = "表名") String tableName, + @Comment(name = "alias", value = "别名") String alias) { + return join(true, DbConstant.RIGHT_JOIN, tableName, alias); + } +} diff --git a/magic-api/src/main/java/org/ssssssss/magicapi/modules/db/table/JoinedTable.java b/magic-api/src/main/java/org/ssssssss/magicapi/modules/db/table/JoinedTable.java new file mode 100644 index 00000000..ecbe11c4 --- /dev/null +++ b/magic-api/src/main/java/org/ssssssss/magicapi/modules/db/table/JoinedTable.java @@ -0,0 +1,39 @@ +package org.ssssssss.magicapi.modules.db.table; + +import org.ssssssss.script.annotation.Comment; + +/** + * 连表操作API + * + * @author tom + */ +public class JoinedTable extends TableBase { + + protected final NamedTable namedTable; + + On on = new On(this); + + /** + * Join类型 + */ + String joinType; + + public JoinedTable(NamedTable namedTable, String tableName, String alias) { + super(tableName, alias, namedTable.sqlModule, + namedTable.rowMapColumnMapper, namedTable.namedTableInterceptors); + this.namedTable = namedTable; + } + + @Override + @Comment("克隆") + public JoinedTable clone() { + JoinedTable joinedTable = (JoinedTable) super.clone(); + joinedTable.on = this.on == null ? null : this.on.clone(); + return joinedTable; + } + + @Comment("拼接on") + public On on() { + return on; + } +} diff --git a/magic-api/src/main/java/org/ssssssss/magicapi/modules/db/table/NamedTable.java b/magic-api/src/main/java/org/ssssssss/magicapi/modules/db/table/NamedTable.java index 4e481fe6..9942d5ec 100644 --- a/magic-api/src/main/java/org/ssssssss/magicapi/modules/db/table/NamedTable.java +++ b/magic-api/src/main/java/org/ssssssss/magicapi/modules/db/table/NamedTable.java @@ -1,14 +1,16 @@ package org.ssssssss.magicapi.modules.db.table; +import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.StringUtils; +import org.springframework.util.CollectionUtils; import org.ssssssss.magicapi.core.context.RequestContext; -import org.ssssssss.magicapi.core.exception.MagicAPIException; -import org.ssssssss.magicapi.core.model.Attributes; import org.ssssssss.magicapi.core.context.RequestEntity; +import org.ssssssss.magicapi.core.exception.MagicAPIException; import org.ssssssss.magicapi.modules.db.BoundSql; -import org.ssssssss.magicapi.modules.db.inteceptor.NamedTableInterceptor; import org.ssssssss.magicapi.modules.db.SQLModule; +import org.ssssssss.magicapi.modules.db.inteceptor.NamedTableInterceptor; import org.ssssssss.magicapi.modules.db.model.Page; +import org.ssssssss.magicapi.modules.db.model.PageResult; import org.ssssssss.magicapi.modules.db.model.SqlMode; import org.ssssssss.script.annotation.Comment; import org.ssssssss.script.runtime.RuntimeContext; @@ -25,17 +27,7 @@ import java.util.stream.Collectors; * * @author mxd */ -public class NamedTable extends Attributes { - - String tableName; - - SQLModule sqlModule; - - String primary; - - String logicDeleteColumn; - - Object logicDeleteValue; +public class NamedTable extends TableBase implements JoinInterface { Map columns = new HashMap<>(); @@ -47,38 +39,20 @@ public class NamedTable extends Attributes { Set excludeColumns = new HashSet<>(); - Function rowMapColumnMapper; - Object defaultPrimaryValue; - boolean useLogic = false; + boolean useDistinct = false; boolean withBlank = false; - List namedTableInterceptors; - Where where = new Where(this); - public NamedTable(String tableName, SQLModule sqlModule, Function rowMapColumnMapper, List namedTableInterceptors) { - this.tableName = tableName; - this.sqlModule = sqlModule; - this.rowMapColumnMapper = rowMapColumnMapper; - this.namedTableInterceptors = namedTableInterceptors; - this.logicDeleteColumn = sqlModule.getLogicDeleteColumn(); - String deleteValue = sqlModule.getLogicDeleteValue(); - this.logicDeleteValue = deleteValue; - if (deleteValue != null) { - boolean isString = deleteValue.startsWith("'") || deleteValue.startsWith("\""); - if (isString && deleteValue.length() > 2) { - this.logicDeleteValue = deleteValue.substring(1, deleteValue.length() - 1); - } else { - try { - this.logicDeleteValue = Integer.parseInt(deleteValue); - } catch (NumberFormatException e) { - this.logicDeleteValue = deleteValue; - } - } - } + List joinedTables = new ArrayList<>(); + + List mappedTables = new ArrayList<>(); + + public NamedTable(String tableName, String alias, SQLModule sqlModule, Function rowMapColumnMapper, List namedTableInterceptors) { + super(tableName, alias, sqlModule, rowMapColumnMapper, namedTableInterceptors); } private NamedTable() { @@ -87,27 +61,94 @@ public class NamedTable extends Attributes { @Override @Comment("克隆") public NamedTable clone() { - NamedTable namedTable = new NamedTable(); - namedTable.tableName = this.tableName; - namedTable.sqlModule = this.sqlModule; - namedTable.primary = this.primary; - namedTable.logicDeleteValue = this.logicDeleteValue; - namedTable.logicDeleteColumn = this.logicDeleteColumn; + NamedTable namedTable = (NamedTable) super.clone(); namedTable.columns = new HashMap<>(this.columns); namedTable.fields = new ArrayList<>(fields); namedTable.groups = new ArrayList<>(groups); namedTable.orders = new ArrayList<>(orders); + namedTable.joinedTables = new ArrayList<>(joinedTables); + namedTable.mappedTables = new ArrayList<>(mappedTables); namedTable.excludeColumns = new HashSet<>(excludeColumns); namedTable.rowMapColumnMapper = this.rowMapColumnMapper; namedTable.defaultPrimaryValue = this.defaultPrimaryValue; + namedTable.useDistinct = this.useDistinct; namedTable.useLogic = this.useLogic; namedTable.withBlank = this.withBlank; namedTable.where = this.where == null ? null : this.where.clone(); - namedTable.namedTableInterceptors = this.namedTableInterceptors; - namedTable.properties = this.properties; return namedTable; } + @Override + @Transient + @Comment("拼接join") + public JoinedTable join(boolean condition, String joinType, String tableName, String alias) { + JoinedTable join = new JoinedTable(this, tableName, alias); + join.joinType = joinType; + if (condition) { + joinedTables.add(join); + } + return join; + } + + @Comment("字段映射") + public NamedTable mapping(@Comment(name = "condition", value = "判断表达式,当为true时拼接条件") boolean condition, + @Comment(name = "tableName", value = "映射表名") String tableName, + @Comment(name = "keyProperty", value = "映射主键属性") String keyProperty, + @Comment(name = "property", value = "源属性") String property, + @Comment(name = "properties", value = "映射属性集合") String... properties) { + if (condition) { + NamedTable map = new NamedTable(tableName, null, sqlModule, rowMapColumnMapper, namedTableInterceptors); + map.column(keyProperty).columns(properties); + map.where.tokens.add(keyProperty); + map.where.params.add(property); + mappedTables.add(map); + } + return this; + } + + @Comment("字段映射") + public NamedTable mapping(@Comment(name = "tableName", value = "映射表名") String tableName, + @Comment(name = "keyProperty", value = "映射主键属性") String keyProperty, + @Comment(name = "property", value = "源属性") String property, + @Comment(name = "properties", value = "映射字段集合") String... properties) { + return mapping(true, tableName, keyProperty, property, properties); + } + + @Comment("字典映射") + public NamedTable dict(@Comment(name = "condition", value = "判断表达式,当为true时拼接条件") boolean condition, + @Comment(name = "tableName", value = "字典项表名") String tableName, + @Comment(name = "typeProperty", value = "字典类型属性") String typeProperty, + @Comment(name = "typeValue", value = "字典类型值") String typeValue, + @Comment(name = "valueProperty", value = "查询字典项属性") String valueProperty, + @Comment(name = "property", value = "源属性") String property, + @Comment(name = "properties", value = "映射字段集合") String... properties) { + if (condition) { + NamedTable map = new NamedTable(tableName, null, sqlModule, rowMapColumnMapper, namedTableInterceptors); + map.column(valueProperty).columns(properties); + map.where.tokens.add(valueProperty); + map.where.params.add(property); + map.where.eq(typeProperty, typeValue); + mappedTables.add(map); + } + return this; + } + + @Comment("字典映射") + public NamedTable dict(@Comment(name = "tableName", value = "字典项表名") String tableName, + @Comment(name = "typeProperty", value = "字典类型字段") String typeProperty, + @Comment(name = "typeValue", value = "字典类型值") String typeValue, + @Comment(name = "valueProperty", value = "查询字典项字段") String valueProperty, + @Comment(name = "property", value = "源属性") String property, + @Comment(name = "properties", value = "映射字段集合") String... properties) { + return dict(true, tableName, typeProperty, typeValue, valueProperty, property, properties); + } + + @Comment("使用去重") + public NamedTable distinct() { + this.useDistinct = true; + return this; + } + @Comment("使用逻辑删除") public NamedTable logic() { this.useLogic = true; @@ -204,6 +245,25 @@ public class NamedTable extends Attributes { return this; } + @Comment("设置查询的列,如`column('t', 'a', 'a1')` -> `select t.a as a1`") + public NamedTable columnAs(@Comment(name = "tableAlias", value = "表别名") String tableAlias, + @Comment(name = "property", value = "查询的列") String property, + @Comment(name = "alias", value = "列别名") String alias) { + if (StringUtils.isNotBlank(property)) { + this.fields.add(tableAlias + DbConstant.DOT + this.rowMapColumnMapper.apply(property) + DbConstant.AS + this.rowMapColumnMapper.apply(alias)); + } + return this; + } + + @Comment("设置查询的列,如`column('a', 'a1')` -> `select a as a1`") + public NamedTable columnAs(@Comment(name = "property", value = "查询的列") String property, + @Comment(name = "alias", value = "列别名") String alias) { + if (StringUtils.isNotBlank(property)) { + this.fields.add(this.rowMapColumnMapper.apply(property) + DbConstant.AS + this.rowMapColumnMapper.apply(alias)); + } + return this; + } + @Comment("拼接`order by xxx asc/desc`") public NamedTable orderBy(@Comment(name = "property", value = "要排序的列") String property, @Comment(name = "sort", value = "`asc`或`desc`") String sort) { @@ -260,8 +320,9 @@ public class NamedTable extends Attributes { builder.append(")"); Object value = sqlModule.insert(new BoundSql(runtimeContext, builder.toString(), entries.stream().map(Map.Entry::getValue).collect(Collectors.toList()), sqlModule), this.primary); if(value == null && StringUtils.isNotBlank(this.primary)){ - return this.columns.get(this.primary); + value = this.columns.get(this.primary); } + data.put(this.primary, value); return value; } @@ -358,30 +419,66 @@ public class NamedTable extends Attributes { return batchInsert(collection, 100); } + private void mapperResults(RuntimeContext runtimeContext, List> results) { + if (CollectionUtils.isEmpty(results)) { + return; + } + for (NamedTable mappedTable : mappedTables) { + Object property = mappedTable.where.params.get(0); + List> mapResults = results.stream() + .filter(x -> ObjectUtils.isNotEmpty(x.get(property))).collect(Collectors.toList()); + if (CollectionUtils.isEmpty(mapResults)) { + continue; + } + String field = mappedTable.where.tokens.get(0); + mappedTable.where.tokens.remove(0); + mappedTable.where.params.remove(0); + mappedTable.where.in(field, mapResults.stream().map(x -> x.get(property)).distinct().collect(Collectors.toList())); + Map> mappedMap = mappedTable.select(runtimeContext).stream() + .collect(Collectors.toMap(x -> x.get(field), x -> { + x.remove(field); + return x; + }, (x, y) -> x)); + mapResults.stream().forEach(x -> { + if (mappedMap.containsKey(x.get(property))) { + x.putAll(mappedMap.get(x.get(property))); + } + }); + } + } + @Comment("执行`select`查询") public List> select(RuntimeContext runtimeContext) { preHandle(SqlMode.SELECT); - return sqlModule.select(buildSelect(runtimeContext)); + List> results = sqlModule.select(buildSelect(runtimeContext)); + mapperResults(runtimeContext, results); + return results; } @Comment("执行`selectOne`查询") public Map selectOne(RuntimeContext runtimeContext) { preHandle(SqlMode.SELECT_ONE); - return sqlModule.selectOne(buildSelect(runtimeContext)); + Map result = sqlModule.selectOne(buildSelect(runtimeContext)); + mapperResults(runtimeContext, Arrays.asList(result)); + return result; } @Comment("执行分页查询") - public Object page(RuntimeContext runtimeContext) { + public PageResult page(RuntimeContext runtimeContext) { preHandle(SqlMode.PAGE); - return sqlModule.page(buildSelect(runtimeContext)); + PageResult pageResult = sqlModule.page(buildSelect(runtimeContext)); + mapperResults(runtimeContext, pageResult.getList()); + return pageResult; } @Comment("执行分页查询,分页条件手动传入") - public Object page(RuntimeContext runtimeContext, + public PageResult page(RuntimeContext runtimeContext, @Comment(name = "limit", value = "限制条数") long limit, @Comment(name = "offset", value = "跳过条数") long offset) { preHandle(SqlMode.PAGE); - return sqlModule.page(buildSelect(runtimeContext), new Page(limit, offset)); + PageResult pageResult = sqlModule.page(buildSelect(runtimeContext), new Page(limit, offset)); + mapperResults(runtimeContext, pageResult.getList()); + return pageResult; } @Comment("执行update语句") @@ -441,8 +538,10 @@ public class NamedTable extends Attributes { public int count(RuntimeContext runtimeContext) { preHandle(SqlMode.COUNT); StringBuilder builder = new StringBuilder(); - builder.append("select count(1) from ").append(tableName); - List params = buildWhere(builder); + builder.append("select count(1) from ").append(getAlisName(tableName)); + List params = new ArrayList<>(); + params.addAll(buildJoin(builder)); + params.addAll(buildWhere(builder)); return sqlModule.selectInt(new BoundSql(runtimeContext, builder.toString(), params, sqlModule)); } @@ -477,13 +576,18 @@ public class NamedTable extends Attributes { List fields = this.fields.stream() .filter(it -> !excludeColumns.contains(it)) .collect(Collectors.toList()); + if (this.useDistinct) { + builder.append("distinct "); + } if (fields.isEmpty()) { - builder.append("*"); + builder.append(withAlis("*")); } else { builder.append(StringUtils.join(fields, ",")); } - builder.append(" from ").append(tableName); - List params = buildWhere(builder); + builder.append(" from ").append(getAlisName(tableName)); + List params = new ArrayList<>(); + params.addAll(buildJoin(builder)); + params.addAll(buildWhere(builder)); if (!groups.isEmpty()) { builder.append(" group by "); builder.append(String.join(",", groups)); @@ -497,16 +601,36 @@ public class NamedTable extends Attributes { return boundSql; } + private List buildJoin(StringBuilder builder) { + List params = new ArrayList<>(); + for (JoinedTable sub : joinedTables) { + builder.append(sub.joinType) + .append(sub.getAlisName(sub.tableName)); + On on = sub.on; + if (!on.isEmpty()) { + on.and(); + on.ne(sub.isUseLogic(), sub.withAlis(logicDeleteColumn), logicDeleteValue); + builder.append(on.getSql()); + params.addAll(on.getParams()); + } else if (sub.isUseLogic()) { + on.ne(sub.withAlis(logicDeleteColumn), logicDeleteValue); + builder.append(on.getSql()); + params.addAll(on.getParams()); + } + } + return params; + } + private List buildWhere(StringBuilder builder) { List params = new ArrayList<>(); if (!where.isEmpty()) { where.and(); - where.ne(useLogic, logicDeleteColumn, logicDeleteValue); + where.ne(useLogic, withAlis(logicDeleteColumn), logicDeleteValue); builder.append(where.getSql()); params.addAll(where.getParams()); } else if (useLogic) { - where.ne(logicDeleteColumn, logicDeleteValue); + where.ne(withAlis(logicDeleteColumn), logicDeleteValue); builder.append(where.getSql()); params.addAll(where.getParams()); } @@ -514,58 +638,6 @@ public class NamedTable extends Attributes { } - /** - * 获取查询的表名 - * - * @return 表名 - */ - @Transient - public String getTableName() { - return tableName; - } - - /** - * 设置表名 - * - * @param tableName 表名 - */ - @Transient - public void setTableName(String tableName) { - this.tableName = tableName; - } - - /** - * 获取SQL模块 - */ - @Transient - public SQLModule getSqlModule() { - return sqlModule; - } - - /** - * 获取主键列 - */ - @Transient - public String getPrimary() { - return primary; - } - - /** - * 获取逻辑删除列 - */ - @Transient - public String getLogicDeleteColumn() { - return logicDeleteColumn; - } - - /** - * 获取逻辑删除值 - */ - @Transient - public Object getLogicDeleteValue() { - return logicDeleteValue; - } - /** * 获取设置的columns */ @@ -657,19 +729,19 @@ public class NamedTable extends Attributes { } /** - * 是否设逻辑了逻辑删除 + * 是否使用排他 */ @Transient - public boolean isUseLogic() { - return useLogic; + public boolean isUseDistinct() { + return useDistinct; } /** - * 设置是否使用逻辑删除 + * 设置是否使用排他 */ @Transient - public void setUseLogic(boolean useLogic) { - this.useLogic = useLogic; + public void setUseDistinct(boolean useDistinct) { + this.useDistinct = useDistinct; } /** diff --git a/magic-api/src/main/java/org/ssssssss/magicapi/modules/db/table/On.java b/magic-api/src/main/java/org/ssssssss/magicapi/modules/db/table/On.java new file mode 100644 index 00000000..11b809a6 --- /dev/null +++ b/magic-api/src/main/java/org/ssssssss/magicapi/modules/db/table/On.java @@ -0,0 +1,532 @@ +package org.ssssssss.magicapi.modules.db.table; + +import org.ssssssss.script.annotation.Comment; + +import java.beans.Transient; +import java.util.function.Function; + +/** + * 连表API的On + * + * @author tom + */ +public class On extends WhereBase implements TableInterface, JoinInterface { + + public On(JoinedTable joinedTable) { + this(joinedTable, true); + } + + public On(JoinedTable joinedTable, boolean needOn) { + super(joinedTable, needOn); + } + + @Override + @Comment("克隆") + public On clone() { + return (On) super.clone(); + } + + @Override + @Transient + public NamedTable getNamedTable() { + return ((JoinedTable) tableBase).namedTable; + } + + @Comment("拼接where") + public Where where() { + return getNamedTable().where(); + } + + @Comment("逻辑过滤") + public On logic() { + super.logic(); + return this; + } + + @Override + @Comment("过滤`null`的参数") + public On notNull() { + return notNull(true); + } + + @Override + @Comment("过滤`blank`的参数") + public On notBlank() { + return notBlank(true); + } + + @Override + @Comment("是否过滤`null`的参数") + public On notNull(boolean flag) { + super.notNull(flag); + return this; + } + + @Override + @Comment("是否过滤`blank`的参数") + public On notBlank(boolean flag) { + super.notBlank(flag); + return this; + } + + @Override + @Comment("等于`=`,如:`eq('name', '老王') ---> name = '老王'`") + public On eq(@Comment(name = "column", value = "数据库中的列名") String column, + @Comment(name = "value", value = "值") Object value) { + return eq(true, column, value); + } + + @Override + @Comment("等于`=`,如:`eq('name', '老王') ---> name = '老王'`") + public On eq(@Comment(name = "condition", value = "判断表达式,当为true时拼接条件") boolean condition, + @Comment(name = "column", value = "数据库中的列名") String column, + @Comment(name = "value", value = "值") Object value) { + super.eq(condition, column, value); + return this; + } + + @Override + @Comment("等于`=`,如:`eq2('t.userId', 'u.id') ---> t.userId = u.id`") + public On eq2(@Comment(name = "column1", value = "数据库中的列名1") String column1, + @Comment(name = "column2", value = "数据库中的列名2") String column2) { + return eq2(true, column1, column2); + } + + @Override + @Comment("等于`=`,如:`eq2('t.userId', 'u.id') ---> t.userId = u.id`") + public On eq2(@Comment(name = "condition", value = "判断表达式,当为true时拼接条件") boolean condition, + @Comment(name = "column1", value = "数据库中的列名1") String column1, + @Comment(name = "column2", value = "数据库中的列名2") String column2) { + super.eq2(condition, column1, column2); + return this; + } + + @Override + @Comment("不等于`<>`,如:`ne('name', '老王') ---> name <> '老王'`") + public On ne(@Comment(name = "column", value = "数据库中的列名") String column, + @Comment(name = "value", value = "值") Object value) { + return ne(true, column, value); + } + + @Override + @Comment("不等于`<>`,如:`ne('name', '老王') ---> name <> '老王'`") + public On ne(@Comment(name = "condition", value = "判断表达式,当为true时拼接条件") boolean condition, + @Comment(name = "column", value = "数据库中的列名") String column, + @Comment(name = "value", value = "值") Object value) { + super.ne(condition, column, value); + return this; + } + + @Override + @Comment("不等于`<>`,如:`ne2('t.name', 'u.name') ---> t.name <> u.name`") + public On ne2(@Comment(name = "column1", value = "数据库中的列名1") String column1, + @Comment(name = "column2", value = "数据库中的列名2") String column2) { + return ne2(true, column1, column2); + } + + @Override + @Comment("不等于`<>`,如:`ne2('t.name', 'u.name') ---> t.name <> u.name`") + public On ne2(@Comment(name = "condition", value = "判断表达式,当为true时拼接条件") boolean condition, + @Comment(name = "column1", value = "数据库中的列名1") String column1, + @Comment(name = "column2", value = "数据库中的列名2") String column2) { + super.ne2(condition, column1, column2); + return this; + } + + @Override + @Comment("between(true, true, 't.createTime', '2023-01-01', '2023-01-31', true, false) ---> t.create_time >= '2023-01-01' and t.create_time < '2023-01-31'") + public On between( + @Comment(name = "startCon", value = "判断表达式,当为true时拼接条件") boolean startCon, + @Comment(name = "endCon", value = "判断表达式,当为true时拼接条件") boolean endCon, + @Comment(name = "column", value = "数据库中的列名") String column, + @Comment(name = "startVal", value = "开始值") Object startVal, + @Comment(name = "endVal", value = "结束值") Object endVal, + @Comment(name = "startContain", value = "包含开始值") boolean startContain, + @Comment(name = "endContain", value = "包含结束值") boolean endContain + ) { + super.between(startCon, endCon, column, startVal, endVal, startContain, endContain); + return this; + } + + @Override + @Comment("between('t.createTime', '2023-01-01', '2023-01-31', true, false) ---> t.create_time >= '2023-01-01' and t.create_time < '2023-01-31'") + public On between( + @Comment(name = "column", value = "数据库中的列名") String column, + @Comment(name = "startVal", value = "开始值") Object startVal, + @Comment(name = "endVal", value = "结束值") Object endVal, + @Comment(name = "startContain", value = "包含开始值") boolean startContain, + @Comment(name = "endContain", value = "包含结束值") boolean endContain + ) { + return between(true,true,column,startVal,endVal,startContain,endContain); + } + + @Override + @Comment("between(true, true, 't.createTime', '2023-01-01', '2023-01-31') ---> t.create_time >= '2023-01-01' and t.create_time <= '2023-01-31'") + public On between( + @Comment(name = "startCon", value = "判断表达式,当为true时拼接条件") boolean startCon, + @Comment(name = "endCon", value = "判断表达式,当为true时拼接条件") boolean endCon, + @Comment(name = "column", value = "数据库中的列名") String column, + @Comment(name = "startVal", value = "开始值") Object startVal, + @Comment(name = "endVal", value = "结束值") Object endVal + ) { + return between(startCon,endCon,column,startVal,endVal,true,true); + } + + @Override + @Comment("between('t.createTime', '2023-01-01', '2023-01-31') ---> t.create_time >= '2023-01-01' and t.create_time <= '2023-01-31'") + public On between( + @Comment(name = "column", value = "数据库中的列名") String column, + @Comment(name = "startVal", value = "开始值") Object startVal, + @Comment(name = "endVal", value = "结束值") Object endVal + ) { + return between(true,true,column,startVal,endVal,true,true); + } + + @Override + @Comment("等于`=`,如:`notExists(true, 'table_name', 'tn', namedWhere -> namedWhere.eq2('tn.aId','a.id').eq('tn.name','老王'), true) ---> not exists(select 1 from table_name as tn namedWhere tn.a_id=a.id and tn.user_id='老王' and tn.del_flag<>1`") + public On notExists(@Comment(name = "condition", value = "判断表达式,当为true时拼接条件") boolean condition, + @Comment(name = "tableName", value = "表名") String tableName, + @Comment(name = "alias", value = "别名") String alias, + @Comment(name = "function", value = "关联条件") Function function, + @Comment(name = "useLogic", value = "使用逻辑删除") boolean useLogic) { + exists(true, condition, tableName, alias, function, useLogic); + return this; + } + + @Override + @Comment("等于`=`,如:`exists('table_name', 'tn', namedWhere -> namedWhere.eq2('tn.aId','a.id').eq('tn.name','老王'), true) ---> exists(select 1 from table_name as tn namedWhere tn.a_id=a.id and tn.user_id='老王' and tn.del_flag<>1`") + public On notExists(@Comment(name = "tableName", value = "表名") String tableName, + @Comment(name = "alias", value = "别名") String alias, + @Comment(name = "function", value = "关联条件") Function function, + @Comment(name = "useLogic", value = "使用逻辑删除") boolean useLogic) { + return notExists(true, tableName, alias, function, useLogic); + } + + @Override + @Comment("等于`=`,如:`exists(true, 'table_name', 'tn', namedWhere -> namedWhere.eq2('tn.aId','a.id').eq('tn.name','老王')) ---> exists(select 1 from table_name as tn namedWhere tn.a_id=a.id and tn.user_id='老王'`") + public On notExists(@Comment(name = "tableName", value = "表名") String tableName, + @Comment(name = "alias", value = "别名") String alias, + @Comment(name = "function", value = "关联条件") Function function) { + return notExists(true, tableName, alias, function, false); + } + + @Override + @Comment("等于`=`,如:`exists(true, 'table_name', 'tn', namedWhere -> namedWhere.eq2('tn.aId','a.id').eq('tn.name','老王'), true) ---> exists(select 1 from table_name as tn namedWhere tn.a_id=a.id and tn.user_id='老王' and tn.del_flag<>1`") + public On exists(@Comment(name = "condition", value = "判断表达式,当为true时拼接条件") boolean condition, + @Comment(name = "tableName", value = "表名") String tableName, + @Comment(name = "alias", value = "别名") String alias, + @Comment(name = "function", value = "关联条件") Function function, + @Comment(name = "useLogic", value = "使用逻辑删除") boolean useLogic) { + exists(false, condition, tableName, alias, function, useLogic); + return this; + } + + @Override + @Comment("等于`=`,如:`exists('table_name', 'tn', namedWhere -> namedWhere.eq2('tn.aId','a.id').eq('tn.name','老王'), true) ---> exists(select 1 from table_name as tn namedWhere tn.a_id=a.id and tn.user_id='老王' and tn.del_flag<>1`") + public On exists(@Comment(name = "tableName", value = "表名") String tableName, + @Comment(name = "alias", value = "别名") String alias, + @Comment(name = "function", value = "关联条件") Function function, + @Comment(name = "useLogic", value = "使用逻辑删除") boolean useLogic) { + return exists(true, tableName, alias, function, useLogic); + } + + @Override + @Comment("等于`=`,如:`exists('table_name', 'tn', namedWhere -> namedWhere.eq2('tn.aId','a.id').eq('tn.name','老王')) ---> exists(select 1 from table_name as tn namedWhere tn.a_id=a.id and tn.user_id='老王'`") + public On exists(@Comment(name = "tableName", value = "表名") String tableName, + @Comment(name = "alias", value = "别名") String alias, + @Comment(name = "function", value = "关联条件") Function function) { + return exists(true, tableName, alias, function, false); + } + + @Override + @Comment("小于`<`,如:`lt('age', 18) ---> age < 18") + public On lt(@Comment(name = "column", value = "数据库中的列名") String column, + @Comment(name = "value", value = "值") Object value) { + return lt(true, column, value); + } + + @Override + @Comment("小于`<`,如:`lt('age', 18) ---> age < 18") + public On lt(@Comment(name = "condition", value = "判断表达式,当为true时拼接条件") boolean condition, + @Comment(name = "column", value = "数据库中的列名") String column, + @Comment(name = "value", value = "值") Object value) { + super.lt(condition, column, value); + return this; + } + + @Override + @Comment("小于`<`,如:`lt2('t.age', 'u.age') ---> t.age < u.age") + public On lt2(@Comment(name = "column1", value = "数据库中的列名1") String column1, + @Comment(name = "column2", value = "数据库中的列名2") String column2) { + return lt2(true, column1, column2); + } + + @Override + @Comment("小于`<`,如:`lt2('t.age', 'u.age') ---> t.age < u.age") + public On lt2(@Comment(name = "condition", value = "判断表达式,当为true时拼接条件") boolean condition, + @Comment(name = "column1", value = "数据库中的列名1") String column1, + @Comment(name = "column2", value = "数据库中的列名2") String column2) { + super.lt2(condition, column1, column2); + return this; + } + + @Override + @Comment("小于等于`<=`,如:`lte('age', 18) ---> age <= 18") + public On lte(@Comment(name = "column", value = "数据库中的列名") String column, + @Comment(name = "value", value = "值") Object value) { + return lte(true, column, value); + } + + @Override + @Comment("小于等于`<=`,如:`lte('age', 18) ---> age <= 18") + public On lte(@Comment(name = "condition", value = "判断表达式,当为true时拼接条件") boolean condition, + @Comment(name = "column", value = "数据库中的列名") String column, + @Comment(name = "value", value = "值") Object value) { + super.lte(condition, column, value); + return this; + } + + @Override + @Comment("小于等于`<=`,如:`lte2('t.age', 'u.age') ---> t.age <= u.age") + public On lte2(@Comment(name = "column1", value = "数据库中的列名1") String column1, + @Comment(name = "column2", value = "数据库中的列名2") String column2) { + return lte2(true, column1, column2); + } + + @Override + @Comment("小于等于`<=`,如:`lte2('t.age', 'u.age') ---> t.age <= u.age") + public On lte2(@Comment(name = "condition", value = "判断表达式,当为true时拼接条件") boolean condition, + @Comment(name = "column1", value = "数据库中的列名1") String column1, + @Comment(name = "column2", value = "数据库中的列名2") String column2) { + super.lte2(condition, column1, column2); + return this; + } + + @Override + @Comment("大于`>`,如:`get('age', 18) ---> age > 18") + public On gt(@Comment(name = "column", value = "数据库中的列名") String column, + @Comment(name = "value", value = "值") Object value) { + return gt(true, column, value); + } + + @Override + @Comment("大于`>`,如:`get('age', 18) ---> age > 18") + public On gt(@Comment(name = "condition", value = "判断表达式,当为true时拼接条件") boolean condition, + @Comment(name = "column", value = "数据库中的列名") String column, + @Comment(name = "value", value = "值") Object value) { + super.gt(condition, column, value); + return this; + } + + @Override + @Comment("大于`>`,如:`get('t.age', 't.age') ---> t.age > u.age") + public On gt2(@Comment(name = "column1", value = "数据库中的列名1") String column1, + @Comment(name = "column2", value = "数据库中的列名2") String column2) { + return gt2(true, column1, column2); + } + + @Override + @Comment("大于`>`,如:`get('t.age', 't.age') ---> t.age > u.age") + public On gt2(@Comment(name = "condition", value = "判断表达式,当为true时拼接条件") boolean condition, + @Comment(name = "column1", value = "数据库中的列名1") String column1, + @Comment(name = "column2", value = "数据库中的列名2") String column2) { + super.gt2(condition, column1, column2); + return this; + } + + @Override + @Comment("大于等于`>=`,如:`get('age', 18) ---> age >= 18") + public On gte(@Comment(name = "column", value = "数据库中的列名") String column, + @Comment(name = "value", value = "值") Object value) { + return gte(true, column, value); + } + + @Override + @Comment("大于等于`>=`,如:`get('age', 18) ---> age >= 18") + public On gte(@Comment(name = "condition", value = "判断表达式,当为true时拼接条件") boolean condition, + @Comment(name = "column", value = "数据库中的列名") String column, + @Comment(name = "value", value = "值") Object value) { + super.gte(condition, column, value); + return this; + } + + @Override + @Comment("大于等于`>=`,如:`get('t.age', 'u.age') ---> t.age >= u.age") + public On gte2(@Comment(name = "column1", value = "数据库中的列名1") String column1, + @Comment(name = "column2", value = "数据库中的列名2") String column2) { + return gte2(true, column1, column2); + } + + @Override + @Comment("大于等于`>=`,如:`get('t.age', 'u.age') ---> t.age >= u.age") + public On gte2(@Comment(name = "condition", value = "判断表达式,当为true时拼接条件") boolean condition, + @Comment(name = "column1", value = "数据库中的列名1") String column1, + @Comment(name = "column2", value = "数据库中的列名2") String column2) { + super.gte2(condition, column1, column2); + return this; + } + + @Override + @Comment("`in`,如:`in('age', [1,2,3]) ---> age in (1,2,3)") + public On in(@Comment(name = "column", value = "数据库中的列名") String column, + @Comment(name = "value", value = "值") Object value) { + return in(true, column, value); + } + + @Override + @Comment("`in`,如:`in('age', [1,2,3]) ---> age in (1,2,3)") + public On in(@Comment(name = "condition", value = "判断表达式,当为true时拼接条件") boolean condition, + @Comment(name = "column", value = "数据库中的列名") String column, + @Comment(name = "value", value = "值") Object value) { + super.in(condition, column, value); + return this; + } + + @Override + @Comment("`not in`,如:`notIn('age', [1,2,3]) ---> age not in (1,2,3)") + public On notIn(@Comment(name = "column", value = "数据库中的列名") String column, + @Comment(name = "value", value = "值") Object value) { + return notIn(true, column, value); + } + + @Override + @Comment("`not in`,如:`notIn('age', [1,2,3]) ---> age not in (1,2,3)") + public On notIn(@Comment(name = "condition", value = "判断表达式,当为true时拼接条件") boolean condition, + @Comment(name = "column", value = "数据库中的列名") String column, + @Comment(name = "value", value = "值") Object value) { + super.notIn(condition, column, value); + return this; + } + + @Override + @Comment("`like`,如:`like('name', '%王%') ---> name like '%王%'") + public On like(@Comment(name = "column", value = "数据库中的列名") String column, + @Comment(name = "value", value = "值") Object value) { + return like(true, column, value); + } + + @Override + @Comment("`like`,如:`like('name', '%王%') ---> name like '%王%'") + public On like(@Comment(name = "condition", value = "判断表达式,当为true时拼接条件") boolean condition, + @Comment(name = "column", value = "数据库中的列名") String column, + @Comment(name = "value", value = "值") Object value) { + super.like(condition, column, value); + return this; + } + + @Override + @Comment("`not like`,如:`notLike('name', '%王%') ---> name not like '%王%'") + public On notLike(@Comment(name = "column", value = "数据库中的列名") String column, + @Comment(name = "value", value = "值") Object value) { + return notLike(true, column, value); + } + + @Override + @Comment("`not like` ,如:`notLike('name', '%王%') ---> name not like '%王%'") + public On notLike(@Comment(name = "condition", value = "判断表达式,当为true时拼接条件") boolean condition, + @Comment(name = "column", value = "数据库中的列名") String column, + @Comment(name = "value", value = "值") Object value) { + super.notLike(condition, column, value); + return this; + } + + @Override + @Comment("`is null`,如:`isNull('name') ---> name is null") + public On isNull(@Comment(name = "column", value = "数据库中的列名") String column) { + return isNull(true, column); + } + + @Override + @Comment("`is null`,如:`isNull('name') ---> name is null") + public On isNull(@Comment(name = "condition", value = "判断表达式,当为true时拼接条件") boolean condition, + @Comment(name = "column", value = "数据库中的列名") String column) { + super.isNull(condition, column); + return this; + } + + @Override + @Comment("`is not null`,如:`isNotNull('name') ---> name is not null") + public On isNotNull(@Comment(name = "column", value = "数据库中的列名") String column) { + return isNotNull(true, column); + } + + @Override + @Comment("`is not null`,如:`isNotNull('name') ---> name is not null") + public On isNotNull(@Comment(name = "condition", value = "判断表达式,当为true时拼接条件") boolean condition, + @Comment(name = "column", value = "数据库中的列名") String column) { + super.isNotNull(condition, column); + return this; + } + + @Override + @Comment("拼接`or`") + public On or() { + super.or(); + return this; + } + + @Override + @Comment("拼接`and`") + public On and() { + super.and(); + return this; + } + + @Override + @Comment("`and`嵌套,如and(it => it.eq('name','李白').ne('status','正常') --> and (name = '李白' and status <> '正常')") + public On and(@Comment(name = "function", value = "回调函数") Function function) { + return and(true, function); + } + + @Override + @Comment("`and`嵌套,如and(it => it.eq('name','李白').ne('status','正常') --> and (name = '李白' and status <> '正常')") + public On and(@Comment(name = "condition", value = "判断表达式,当为true时拼接条件") boolean condition, + @Comment(name = "function", value = "回调函数") Function function) { + super.and(condition, function); + return this; + } + + @Override + @Comment("拼接`order by xxx asc/desc`") + public On orderBy(@Comment(name = "column", value = "要排序的列") String column, + @Comment(name = "sort", value = "`asc`或`desc`") String sort) { + + this.getNamedTable().orderBy(column, sort); + return this; + } + + @Override + @Comment("拼接`order by xxx asc`") + public On orderBy(@Comment(name = "column", value = "要排序的列") String column) { + return orderBy(column, "asc"); + } + + @Override + @Comment("拼接`order by xxx desc`") + public On orderByDesc(@Comment(name = "column", value = "要排序的列") String column) { + return orderBy(column, "desc"); + } + + @Override + @Comment("拼接`group by`") + public On groupBy(@Comment("要分组的列") String... columns) { + this.getNamedTable().groupBy(columns); + return this; + } + + @Override + protected String getSql() { + remove(); + if (isEmpty()) { + return ""; + } + return (needWhere ? " on " : "") + String.join(" ", tokens); + } + + @Override + @Transient + @Comment("拼接join") + public JoinedTable join(boolean condition, String joinType, String tableName, String alias) { + return getNamedTable().join(condition, joinType, tableName, alias); + } +} diff --git a/magic-api/src/main/java/org/ssssssss/magicapi/modules/db/table/TableBase.java b/magic-api/src/main/java/org/ssssssss/magicapi/modules/db/table/TableBase.java new file mode 100644 index 00000000..eabbeed6 --- /dev/null +++ b/magic-api/src/main/java/org/ssssssss/magicapi/modules/db/table/TableBase.java @@ -0,0 +1,177 @@ +package org.ssssssss.magicapi.modules.db.table; + +import org.apache.commons.lang3.StringUtils; +import org.ssssssss.magicapi.core.model.Attributes; +import org.ssssssss.magicapi.modules.db.SQLModule; +import org.ssssssss.magicapi.modules.db.inteceptor.NamedTableInterceptor; +import org.ssssssss.script.annotation.Comment; + +import java.beans.Transient; +import java.util.List; +import java.util.function.Function; + +/** + * 表操作基类 + * + * @author tom + */ +public class TableBase extends Attributes { + + String tableName; + + String alias; + + SQLModule sqlModule; + + String primary; + + String logicDeleteColumn; + + Object logicDeleteValue; + + boolean useLogic = false; + + Function rowMapColumnMapper; + + List namedTableInterceptors; + + public TableBase(String tableName, String alias, SQLModule sqlModule, Function rowMapColumnMapper, + List namedTableInterceptors) { + this.tableName = tableName; + this.alias = alias; + this.sqlModule = sqlModule; + this.rowMapColumnMapper = rowMapColumnMapper; + this.namedTableInterceptors = namedTableInterceptors; + this.logicDeleteColumn = sqlModule.getLogicDeleteColumn(); + String deleteValue = sqlModule.getLogicDeleteValue(); + this.logicDeleteValue = deleteValue; + if (deleteValue != null) { + boolean isString = deleteValue.startsWith("'") || deleteValue.startsWith("\""); + if (isString && deleteValue.length() > 2) { + this.logicDeleteValue = deleteValue.substring(1, deleteValue.length() - 1); + } else { + try { + this.logicDeleteValue = Integer.parseInt(deleteValue); + } catch (NumberFormatException e) { + this.logicDeleteValue = deleteValue; + } + } + } + } + + protected TableBase() { + } + + @Override + @Comment("克隆") + public TableBase clone() { + TableBase tableBase = new TableBase(); + tableBase.tableName = this.tableName; + tableBase.alias = this.alias; + tableBase.sqlModule = this.sqlModule; + tableBase.primary = this.primary; + tableBase.logicDeleteValue = this.logicDeleteValue; + tableBase.logicDeleteColumn = this.logicDeleteColumn; + tableBase.rowMapColumnMapper = this.rowMapColumnMapper; + tableBase.namedTableInterceptors = this.namedTableInterceptors; + tableBase.properties = this.properties; + return tableBase; + } + + + /** + * 获取别名 + * + * @return 名 + */ + @Transient + String getAlisName(String name) { + if (StringUtils.isNotEmpty(alias)) { + return name + DbConstant.AS + alias; + } + return name; + } + + + /** + * 获取别名 + * + * @return 名 + */ + @Transient + String withAlis(String name) { + if (StringUtils.isNotEmpty(alias)) { + return alias + DbConstant.DOT + name; + } + return name; + } + + + /** + * 获取查询的表名 + * + * @return 表名 + */ + @Transient + public String getTableName() { + return tableName; + } + + /** + * 设置表名 + * + * @param tableName 表名 + */ + @Transient + public void setTableName(String tableName) { + this.tableName = tableName; + } + + /** + * 获取SQL模块 + */ + @Transient + public SQLModule getSqlModule() { + return sqlModule; + } + + /** + * 获取主键列 + */ + @Transient + public String getPrimary() { + return primary; + } + + /** + * 获取逻辑删除列 + */ + @Transient + public String getLogicDeleteColumn() { + return logicDeleteColumn; + } + + /** + * 获取逻辑删除值 + */ + @Transient + public Object getLogicDeleteValue() { + return logicDeleteValue; + } + + /** + * 是否设逻辑了逻辑删除 + */ + @Transient + public boolean isUseLogic() { + return useLogic; + } + + /** + * 设置是否使用逻辑删除 + */ + @Transient + public void setUseLogic(boolean useLogic) { + this.useLogic = useLogic; + } +} diff --git a/magic-api/src/main/java/org/ssssssss/magicapi/modules/db/table/TableInterface.java b/magic-api/src/main/java/org/ssssssss/magicapi/modules/db/table/TableInterface.java new file mode 100644 index 00000000..e3cd5667 --- /dev/null +++ b/magic-api/src/main/java/org/ssssssss/magicapi/modules/db/table/TableInterface.java @@ -0,0 +1,75 @@ +package org.ssssssss.magicapi.modules.db.table; + +import org.ssssssss.magicapi.modules.db.model.PageResult; +import org.ssssssss.script.annotation.Comment; +import org.ssssssss.script.runtime.RuntimeContext; + +import java.beans.Transient; +import java.util.List; +import java.util.Map; + +/** + * 表查询操作接口 + * + * @author tom + */ +public interface TableInterface { + + @Transient + NamedTable getNamedTable(); + + @Comment("拼接`order by xxx asc/desc`") + default TableInterface orderBy(@Comment(name = "column", value = "要排序的列") String column, + @Comment(name = "sort", value = "`asc`或`desc`") String sort) { + this.getNamedTable().orderBy(column, sort); + return this; + } + + @Comment("拼接`order by xxx asc`") + default TableInterface orderBy(@Comment(name = "column", value = "要排序的列") String column) { + return orderBy(column, "asc"); + } + + @Comment("拼接`order by xxx desc`") + default TableInterface orderByDesc(@Comment(name = "column", value = "要排序的列") String column) { + return orderBy(column, "desc"); + } + + @Comment("拼接`group by`") + default TableInterface groupBy(@Comment("要分组的列") String... columns) { + this.getNamedTable().groupBy(columns); + return this; + } + + @Comment("执行分页查询") + default PageResult page(RuntimeContext runtimeContext) { + return getNamedTable().page(runtimeContext); + } + + @Comment("执行分页查询,分页条件手动传入") + default PageResult page(RuntimeContext runtimeContext, + @Comment(name = "limit", value = "限制条数") long limit, + @Comment(name = "offset", value = "跳过条数") long offset) { + return getNamedTable().page(runtimeContext, limit, offset); + } + + @Comment("执行select查询") + default List> select(RuntimeContext runtimeContext) { + return getNamedTable().select(runtimeContext); + } + + @Comment("执行selectOne查询") + default Map selectOne(RuntimeContext runtimeContext) { + return getNamedTable().selectOne(runtimeContext); + } + + @Comment("查询条数") + default int count(RuntimeContext runtimeContext) { + return getNamedTable().count(runtimeContext); + } + + @Comment("查询是否存在") + default boolean exists(RuntimeContext runtimeContext) { + return getNamedTable().exists(runtimeContext); + } +} diff --git a/magic-api/src/main/java/org/ssssssss/magicapi/modules/db/table/Where.java b/magic-api/src/main/java/org/ssssssss/magicapi/modules/db/table/Where.java index 6b3067bd..7b28e825 100644 --- a/magic-api/src/main/java/org/ssssssss/magicapi/modules/db/table/Where.java +++ b/magic-api/src/main/java/org/ssssssss/magicapi/modules/db/table/Where.java @@ -1,12 +1,10 @@ package org.ssssssss.magicapi.modules.db.table; -import org.apache.commons.lang3.StringUtils; import org.ssssssss.script.annotation.Comment; -import org.ssssssss.script.functions.StreamExtension; import org.ssssssss.script.runtime.RuntimeContext; import java.beans.Transient; -import java.util.*; +import java.util.Map; import java.util.function.Function; /** @@ -14,485 +12,570 @@ import java.util.function.Function; * * @author mxd */ -public class Where { - - private final List tokens = new ArrayList<>(); - - private final List params = new ArrayList<>(); - - private final NamedTable namedTable; - - private final boolean needWhere; - - private boolean notNull = false; - - private boolean notBlank = false; +public class Where extends WhereBase implements TableInterface { public Where(NamedTable namedTable) { this(namedTable, true); } public Where(NamedTable namedTable, boolean needWhere) { - this.namedTable = namedTable; - this.needWhere = needWhere; + super(namedTable, needWhere); } @Override @Comment("克隆") public Where clone() { - Where where = new Where(this.namedTable, this.needWhere); - where.tokens.addAll(this.tokens); - where.params.addAll(this.params); - where.notNull = this.notNull; - where.notBlank = this.notBlank; - return where; + return (Where) super.clone(); } + @Override + @Transient + public NamedTable getNamedTable() { + return (NamedTable) tableBase; + } + + @Override + @Comment("使用逻辑删除") + public Where logic() { + super.logic(); + return this; + } + + @Override @Comment("过滤`null`的参数") public Where notNull() { return notNull(true); } + @Override @Comment("过滤`blank`的参数") public Where notBlank() { return notBlank(true); } + @Override @Comment("是否过滤`null`的参数") public Where notNull(boolean flag) { - this.notNull = flag; + super.notNull(flag); return this; } + @Override @Comment("是否过滤`blank`的参数") public Where notBlank(boolean flag) { - this.notBlank = flag; + super.notBlank(flag); return this; } + @Override @Comment("等于`=`,如:`eq('name', '老王') ---> name = '老王'`") public Where eq(@Comment(name = "column", value = "数据库中的列名") String column, @Comment(name = "value", value = "值") Object value) { return eq(true, column, value); } + @Override @Comment("等于`=`,如:`eq('name', '老王') ---> name = '老王'`") public Where eq(@Comment(name = "condition", value = "判断表达式,当为true时拼接条件") boolean condition, @Comment(name = "column", value = "数据库中的列名") String column, @Comment(name = "value", value = "值") Object value) { - if (condition && filterNullAndBlank(value)) { - tokens.add(namedTable.rowMapColumnMapper.apply(column)); - if (value == null) { - append(" is null"); - } else { - params.add(value); - append(" = ?"); - } - appendAnd(); - } + super.eq(condition, column, value); + return this; + } + + @Override + @Comment("等于`=`,如:`eq2('t.userId', 'u.id') ---> t.userId = u.id`") + public Where eq2(@Comment(name = "column1", value = "数据库中的列名1") String column1, + @Comment(name = "column2", value = "数据库中的列名2") String column2) { + return eq2(true, column1, column2); + } + + @Override + @Comment("等于`=`,如:`eq2('t.userId', 'u.id') ---> t.userId = u.id`") + public Where eq2(@Comment(name = "condition", value = "判断表达式,当为true时拼接条件") boolean condition, + @Comment(name = "column1", value = "数据库中的列名1") String column1, + @Comment(name = "column2", value = "数据库中的列名2") String column2) { + super.eq2(condition, column1, column2); return this; } + @Override @Comment("不等于`<>`,如:`ne('name', '老王') ---> name <> '老王'`") public Where ne(@Comment(name = "column", value = "数据库中的列名") String column, @Comment(name = "value", value = "值") Object value) { return ne(true, column, value); } + @Override @Comment("不等于`<>`,如:`ne('name', '老王') ---> name <> '老王'`") public Where ne(@Comment(name = "condition", value = "判断表达式,当为true时拼接条件") boolean condition, @Comment(name = "column", value = "数据库中的列名") String column, @Comment(name = "value", value = "值") Object value) { - if (condition && filterNullAndBlank(value)) { - append(namedTable.rowMapColumnMapper.apply(column)); - if (value == null) { - append("is not null"); - } else { - params.add(value); - append("<> ?"); - } - appendAnd(); - } + super.ne(condition, column, value); return this; } + @Override + @Comment("不等于`<>`,如:`ne2('t.name', 'u.name') ---> t.name <> u.name`") + public Where ne2(@Comment(name = "column1", value = "数据库中的列名1") String column1, + @Comment(name = "column2", value = "数据库中的列名2") String column2) { + return ne2(true, column1, column2); + } + + @Override + @Comment("不等于`<>`,如:`ne2('t.name', 'u.name') ---> t.name <> u.name`") + public Where ne2(@Comment(name = "condition", value = "判断表达式,当为true时拼接条件") boolean condition, + @Comment(name = "column1", value = "数据库中的列名1") String column1, + @Comment(name = "column2", value = "数据库中的列名2") String column2) { + super.ne2(condition, column1, column2); + return this; + } + + @Override @Comment("小于`<`,如:`lt('age', 18) ---> age < 18") public Where lt(@Comment(name = "column", value = "数据库中的列名") String column, @Comment(name = "value", value = "值") Object value) { return lt(true, column, value); } + @Override @Comment("小于`<`,如:`lt('age', 18) ---> age < 18") public Where lt(@Comment(name = "condition", value = "判断表达式,当为true时拼接条件") boolean condition, @Comment(name = "column", value = "数据库中的列名") String column, @Comment(name = "value", value = "值") Object value) { - return append(condition, column, " < ?", value); + super.lt(condition, column, value); + return this; } + @Override + @Comment("小于`<`,如:`lt2('t.age', 'u.age') ---> t.age < u.age") + public Where lt2(@Comment(name = "column1", value = "数据库中的列名1") String column1, + @Comment(name = "column2", value = "数据库中的列名2") String column2) { + return lt2(true, column1, column2); + } + + @Override + @Comment("小于`<`,如:`lt2('t.age', 'u.age') ---> t.age < u.age") + public Where lt2(@Comment(name = "condition", value = "判断表达式,当为true时拼接条件") boolean condition, + @Comment(name = "column1", value = "数据库中的列名1") String column1, + @Comment(name = "column2", value = "数据库中的列名2") String column2) { + super.lt2(condition, column1, column2); + return this; + } + + @Override @Comment("小于等于`<=`,如:`lte('age', 18) ---> age <= 18") public Where lte(@Comment(name = "column", value = "数据库中的列名") String column, @Comment(name = "value", value = "值") Object value) { return lte(true, column, value); } + @Override @Comment("小于等于`<=`,如:`lte('age', 18) ---> age <= 18") public Where lte(@Comment(name = "condition", value = "判断表达式,当为true时拼接条件") boolean condition, @Comment(name = "column", value = "数据库中的列名") String column, @Comment(name = "value", value = "值") Object value) { - return append(condition, column, " <= ?", value); + super.lte(condition, column, value); + return this; + } + + @Override + @Comment("小于等于`<=`,如:`lte2('t.age', 'u.age') ---> t.age <= u.age") + public Where lte2(@Comment(name = "column1", value = "数据库中的列名1") String column1, + @Comment(name = "column2", value = "数据库中的列名2") String column2) { + return lte2(true, column1, column2); + } + + @Override + @Comment("小于等于`<=`,如:`lte2('t.age', 'u.age') ---> t.age <= u.age") + public Where lte2(@Comment(name = "condition", value = "判断表达式,当为true时拼接条件") boolean condition, + @Comment(name = "column1", value = "数据库中的列名1") String column1, + @Comment(name = "column2", value = "数据库中的列名2") String column2) { + super.lte2(condition, column1, column2); + return this; } + @Override @Comment("大于`>`,如:`get('age', 18) ---> age > 18") public Where gt(@Comment(name = "column", value = "数据库中的列名") String column, @Comment(name = "value", value = "值") Object value) { return gt(true, column, value); } + @Override @Comment("大于`>`,如:`get('age', 18) ---> age > 18") public Where gt(@Comment(name = "condition", value = "判断表达式,当为true时拼接条件") boolean condition, @Comment(name = "column", value = "数据库中的列名") String column, @Comment(name = "value", value = "值") Object value) { - return append(condition, column, " > ?", value); + super.gt(condition, column, value); + return this; + } + + @Override + @Comment("大于`>`,如:`get('t.age', 't.age') ---> t.age > u.age") + public Where gt2(@Comment(name = "column1", value = "数据库中的列名1") String column1, + @Comment(name = "column2", value = "数据库中的列名2") String column2) { + return gt2(true, column1, column2); } + @Override + @Comment("大于`>`,如:`get('t.age', 't.age') ---> t.age > u.age") + public Where gt2(@Comment(name = "condition", value = "判断表达式,当为true时拼接条件") boolean condition, + @Comment(name = "column1", value = "数据库中的列名1") String column1, + @Comment(name = "column2", value = "数据库中的列名2") String column2) { + super.gt2(condition, column1, column2); + return this; + } + + @Override @Comment("大于等于`>=`,如:`get('age', 18) ---> age >= 18") public Where gte(@Comment(name = "column", value = "数据库中的列名") String column, @Comment(name = "value", value = "值") Object value) { return gte(true, column, value); } + @Override @Comment("大于等于`>=`,如:`get('age', 18) ---> age >= 18") public Where gte(@Comment(name = "condition", value = "判断表达式,当为true时拼接条件") boolean condition, @Comment(name = "column", value = "数据库中的列名") String column, @Comment(name = "value", value = "值") Object value) { - return append(condition, column, " >= ?", value); + super.gte(condition, column, value); + return this; + } + + @Override + @Comment("大于等于`>=`,如:`get('t.age', 'u.age') ---> t.age >= u.age") + public Where gte2(@Comment(name = "column1", value = "数据库中的列名1") String column1, + @Comment(name = "column2", value = "数据库中的列名2") String column2) { + return gte2(true, column1, column2); } + @Override + @Comment("大于等于`>=`,如:`get('t.age', 'u.age') ---> t.age >= u.age") + public Where gte2(@Comment(name = "condition", value = "判断表达式,当为true时拼接条件") boolean condition, + @Comment(name = "column1", value = "数据库中的列名1") String column1, + @Comment(name = "column2", value = "数据库中的列名2") String column2) { + super.gte2(condition, column1, column2); + return this; + } + + @Override @Comment("`in`,如:`in('age', [1,2,3]) ---> age in (1,2,3)") public Where in(@Comment(name = "column", value = "数据库中的列名") String column, @Comment(name = "value", value = "值") Object value) { return in(true, column, value); } + @Override @Comment("`in`,如:`in('age', [1,2,3]) ---> age in (1,2,3)") public Where in(@Comment(name = "condition", value = "判断表达式,当为true时拼接条件") boolean condition, @Comment(name = "column", value = "数据库中的列名") String column, @Comment(name = "value", value = "值") Object value) { - if (condition && value != null) { - List objects = StreamExtension.arrayLikeToList(value); - if (objects.size() > 0) { - append(namedTable.rowMapColumnMapper.apply(column)); - append(" in ("); - append(String.join(",", Collections.nCopies(objects.size(), "?"))); - append(")"); - appendAnd(); - params.addAll(objects); - } - } + super.in(condition, column, value); return this; } + @Override @Comment("`not in`,如:`notIn('age', [1,2,3]) ---> age not in (1,2,3)") public Where notIn(@Comment(name = "column", value = "数据库中的列名") String column, @Comment(name = "value", value = "值") Object value) { return notIn(true, column, value); } + @Override @Comment("`not in`,如:`notIn('age', [1,2,3]) ---> age not in (1,2,3)") public Where notIn(@Comment(name = "condition", value = "判断表达式,当为true时拼接条件") boolean condition, @Comment(name = "column", value = "数据库中的列名") String column, @Comment(name = "value", value = "值") Object value) { - if (condition && value != null) { - List objects = StreamExtension.arrayLikeToList(value); - if (objects.size() > 0) { - append(namedTable.rowMapColumnMapper.apply(column)); - append("not in ("); - append(String.join(",", Collections.nCopies(objects.size(), "?"))); - append(")"); - appendAnd(); - params.addAll(objects); - } - } + super.notIn(condition, column, value); return this; } + @Override @Comment("`like`,如:`like('name', '%王%') ---> name like '%王%'") public Where like(@Comment(name = "column", value = "数据库中的列名") String column, @Comment(name = "value", value = "值") Object value) { return like(true, column, value); } + @Override @Comment("`like`,如:`like('name', '%王%') ---> name like '%王%'") public Where like(@Comment(name = "condition", value = "判断表达式,当为true时拼接条件") boolean condition, @Comment(name = "column", value = "数据库中的列名") String column, @Comment(name = "value", value = "值") Object value) { - return append(condition, column, "like ?", value); + super.like(condition, column, value); + return this; } + @Override @Comment("`not like`,如:`notLike('name', '%王%') ---> name not like '%王%'") public Where notLike(@Comment(name = "column", value = "数据库中的列名") String column, @Comment(name = "value", value = "值") Object value) { return notLike(true, column, value); } + @Override @Comment("`not like` ,如:`notLike('name', '%王%') ---> name not like '%王%'") public Where notLike(@Comment(name = "condition", value = "判断表达式,当为true时拼接条件") boolean condition, @Comment(name = "column", value = "数据库中的列名") String column, @Comment(name = "value", value = "值") Object value) { - return append(condition, column, "not like ?", value); + super.notLike(condition, column, value); + return this; } + @Override @Comment("`is null`,如:`isNull('name') ---> name is null") public Where isNull(@Comment(name = "column", value = "数据库中的列名") String column) { return isNull(true, column); } + @Override @Comment("`is null`,如:`isNull('name') ---> name is null") public Where isNull(@Comment(name = "condition", value = "判断表达式,当为true时拼接条件") boolean condition, @Comment(name = "column", value = "数据库中的列名") String column) { - if (condition) { - append(namedTable.rowMapColumnMapper.apply(column)); - append("is null"); - appendAnd(); - } + super.isNull(condition, column); return this; } + @Override @Comment("`is not null`,如:`isNotNull('name') ---> name is not null") public Where isNotNull(@Comment(name = "column", value = "数据库中的列名") String column) { return isNotNull(true, column); } + @Override @Comment("`is not null`,如:`isNotNull('name') ---> name is not null") public Where isNotNull(@Comment(name = "condition", value = "判断表达式,当为true时拼接条件") boolean condition, @Comment(name = "column", value = "数据库中的列名") String column) { - if (condition) { - append(namedTable.rowMapColumnMapper.apply(column)); - append("is not null"); - appendAnd(); - } + super.isNotNull(condition, column); return this; } + @Override + @Comment("between('t.createTime', '2023-01-01', '2023-01-31', true, false) ---> t.create_time >= '2023-01-01' and t.create_time < '2023-01-31'") + public Where between( + @Comment(name = "column", value = "数据库中的列名") String column, + @Comment(name = "startVal", value = "开始值") Object startVal, + @Comment(name = "endVal", value = "结束值") Object endVal, + @Comment(name = "startContain", value = "包含开始值") boolean startContain, + @Comment(name = "endContain", value = "包含结束值") boolean endContain + ) { + return between(true,true,column,startVal,endVal,startContain,endContain); + } + + @Override + @Comment("between(true, true, 't.createTime', '2023-01-01', '2023-01-31') ---> t.create_time >= '2023-01-01' and t.create_time <= '2023-01-31'") + public Where between( + @Comment(name = "startCon", value = "判断表达式,当为true时拼接条件") boolean startCon, + @Comment(name = "endCon", value = "判断表达式,当为true时拼接条件") boolean endCon, + @Comment(name = "column", value = "数据库中的列名") String column, + @Comment(name = "startVal", value = "开始值") Object startVal, + @Comment(name = "endVal", value = "结束值") Object endVal + ) { + return between(startCon,endCon,column,startVal,endVal,true,true); + } + + @Override + @Comment("between('t.createTime', '2023-01-01', '2023-01-31') ---> t.create_time >= '2023-01-01' and t.create_time <= '2023-01-31'") + public Where between( + @Comment(name = "column", value = "数据库中的列名") String column, + @Comment(name = "startVal", value = "开始值") Object startVal, + @Comment(name = "endVal", value = "结束值") Object endVal + ) { + return between(true,true,column,startVal,endVal,true,true); + } + + @Override + @Comment("between(true, true, 't.createTime', '2023-01-01', '2023-01-31', true, false) ---> t.create_time >= '2023-01-01' and t.create_time < '2023-01-31'") + public Where between( + @Comment(name = "startCon", value = "判断表达式,当为true时拼接条件") boolean startCon, + @Comment(name = "endCon", value = "判断表达式,当为true时拼接条件") boolean endCon, + @Comment(name = "column", value = "数据库中的列名") String column, + @Comment(name = "startVal", value = "开始值") Object startVal, + @Comment(name = "endVal", value = "结束值") Object endVal, + @Comment(name = "startContain", value = "包含开始值") boolean startContain, + @Comment(name = "endContain", value = "包含结束值") boolean endContain + ) { + super.between(startCon, endCon, column, startVal, endVal, startContain, endContain); + return this; + } + + @Override + @Comment("等于`=`,如:`notExists(true, 'table_name', 'tn', namedWhere -> namedWhere.eq2('tn.aId','a.id').eq('tn.name','老王'), true) ---> not exists(select 1 from table_name as tn namedWhere tn.a_id=a.id and tn.user_id='老王' and tn.del_flag<>1`") + public Where notExists(@Comment(name = "condition", value = "判断表达式,当为true时拼接条件") boolean condition, + @Comment(name = "tableName", value = "表名") String tableName, + @Comment(name = "alias", value = "别名") String alias, + @Comment(name = "function", value = "关联条件") Function function, + @Comment(name = "useLogic", value = "使用逻辑删除") boolean useLogic) { + exists(true, condition, tableName, alias, function, useLogic); + return this; + } + + @Override + @Comment("等于`=`,如:`exists('table_name', 'tn', namedWhere -> namedWhere.eq2('tn.aId','a.id').eq('tn.name','老王'), true) ---> exists(select 1 from table_name as tn namedWhere tn.a_id=a.id and tn.user_id='老王' and tn.del_flag<>1`") + public Where notExists(@Comment(name = "tableName", value = "表名") String tableName, + @Comment(name = "alias", value = "别名") String alias, + @Comment(name = "function", value = "关联条件") Function function, + @Comment(name = "useLogic", value = "使用逻辑删除") boolean useLogic) { + return notExists(true, tableName, alias, function, useLogic); + } + + @Override + @Comment("等于`=`,如:`exists(true, 'table_name', 'tn', namedWhere -> namedWhere.eq2('tn.aId','a.id').eq('tn.name','老王')) ---> exists(select 1 from table_name as tn namedWhere tn.a_id=a.id and tn.user_id='老王'`") + public Where notExists(@Comment(name = "tableName", value = "表名") String tableName, + @Comment(name = "alias", value = "别名") String alias, + @Comment(name = "function", value = "关联条件") Function function) { + return notExists(true, tableName, alias, function, false); + } + + @Override + @Comment("等于`=`,如:`exists(true, 'table_name', 'tn', namedWhere -> namedWhere.eq2('tn.aId','a.id').eq('tn.name','老王'), true) ---> exists(select 1 from table_name as tn namedWhere tn.a_id=a.id and tn.user_id='老王' and tn.del_flag<>1`") + public Where exists(@Comment(name = "condition", value = "判断表达式,当为true时拼接条件") boolean condition, + @Comment(name = "tableName", value = "表名") String tableName, + @Comment(name = "alias", value = "别名") String alias, + @Comment(name = "function", value = "关联条件") Function function, + @Comment(name = "useLogic", value = "使用逻辑删除") boolean useLogic) { + super.exists(false, condition, tableName, alias, function, useLogic); + return this; + } + + @Override + @Comment("等于`=`,如:`exists('table_name', 'tn', namedWhere -> namedWhere.eq2('tn.aId','a.id').eq('tn.name','老王'), true) ---> exists(select 1 from table_name as tn namedWhere tn.a_id=a.id and tn.user_id='老王' and tn.del_flag<>1`") + public Where exists(@Comment(name = "tableName", value = "表名") String tableName, + @Comment(name = "alias", value = "别名") String alias, + @Comment(name = "function", value = "关联条件") Function function, + @Comment(name = "useLogic", value = "使用逻辑删除") boolean useLogic) { + return exists(true, tableName, alias, function, useLogic); + } + + @Override + @Comment("等于`=`,如:`exists('table_name', 'tn', namedWhere -> namedWhere.eq2('tn.aId','a.id').eq('tn.name','老王')) ---> exists(select 1 from table_name as tn namedWhere tn.a_id=a.id and tn.user_id='老王'`") + public Where exists(@Comment(name = "tableName", value = "表名") String tableName, + @Comment(name = "alias", value = "别名") String alias, + @Comment(name = "function", value = "关联条件") Function function) { + return exists(true, tableName, alias, function, false); + } + + @Override @Comment("拼接`or`") public Where or() { appendOr(); return this; } + @Override @Comment("拼接`and`") public Where and() { appendAnd(); return this; } + @Override @Comment("`and`嵌套,如and(it => it.eq('name','李白').ne('status','正常') --> and (name = '李白' and status <> '正常')") - public Where and(@Comment(name = "function", value = "回调函数") Function function) { + public Where and(@Comment(name = "function", value = "回调函数") Function function) { return and(true, function); } + @Override @Comment("`and`嵌套,如and(it => it.eq('name','李白').ne('status','正常') --> and (name = '李白' and status <> '正常')") public Where and(@Comment(name = "condition", value = "判断表达式,当为true时拼接条件") boolean condition, - @Comment(name = "function", value = "回调函数") Function function) { - if (condition) { - Where expr = function.apply(new Object[]{new Where(this.namedTable, false)}); - this.params.addAll(expr.params); - append("("); - append(expr.getSql()); - append(")"); - appendAnd(); - } + @Comment(name = "function", value = "回调函数") Function function) { + super.and(condition, function); return this; } + @Override @Comment("拼接`order by xxx asc/desc`") public Where orderBy(@Comment(name = "column", value = "要排序的列") String column, @Comment(name = "sort", value = "`asc`或`desc`") String sort) { - this.namedTable.orderBy(column, sort); + + this.getNamedTable().orderBy(column, sort); return this; } + @Override @Comment("拼接`order by xxx asc`") public Where orderBy(@Comment(name = "column", value = "要排序的列") String column) { return orderBy(column, "asc"); } + @Override @Comment("拼接`order by xxx desc`") public Where orderByDesc(@Comment(name = "column", value = "要排序的列") String column) { return orderBy(column, "desc"); } + @Override @Comment("拼接`group by`") public Where groupBy(@Comment("要分组的列") String... columns) { - this.namedTable.groupBy(columns); + this.getNamedTable().groupBy(columns); return this; } @Comment("保存到表中,当主键有值时则修改,否则插入") public Object save(RuntimeContext runtimeContext) { - return namedTable.save(runtimeContext); + return getNamedTable().save(runtimeContext); } @Comment("保存到表中,当主键有值时则修改,否则插入") public Object save(RuntimeContext runtimeContext, @Comment(name = "beforeQuery", value = "是否根据id查询有没有数据") boolean beforeQuery) { - return namedTable.save(runtimeContext, beforeQuery); + return getNamedTable().save(runtimeContext, beforeQuery); } @Comment("保存到表中,当主键有值时则修改,否则插入") public Object save(RuntimeContext runtimeContext, @Comment(name = "data", value = "各项列和值") Map data) { - return namedTable.save(runtimeContext, data); + return getNamedTable().save(runtimeContext, data); } @Comment("保存到表中,当主键有值时则修改,否则插入") public Object save(RuntimeContext runtimeContext, @Comment(name = "data", value = "各项列和值") Map data, @Comment(name = "beforeQuery", value = "是否根据id查询有没有数据") boolean beforeQuery) { - return namedTable.save(runtimeContext, data, beforeQuery); + return getNamedTable().save(runtimeContext, data, beforeQuery); } @Comment("执行插入语句,返回主键") public Object insert(RuntimeContext runtimeContext) { - return namedTable.insert(runtimeContext); + return getNamedTable().insert(runtimeContext); } @Comment("执行插入语句,返回主键") public Object insert(RuntimeContext runtimeContext, @Comment(name = "data", value = "各项列和值") Map data) { - return namedTable.insert(runtimeContext, data); + return getNamedTable().insert(runtimeContext, data); } @Comment("执行update语句") public int update(RuntimeContext runtimeContext) { - return namedTable.update(runtimeContext); + return getNamedTable().update(runtimeContext); } @Comment("执行delete语句") public int delete(RuntimeContext runtimeContext) { - return namedTable.delete(runtimeContext); + return getNamedTable().delete(runtimeContext); } @Comment("执行update语句") public int update(RuntimeContext runtimeContext, @Comment(name = "data", value = "各项列和值") Map data) { - return namedTable.update(runtimeContext, data); + return getNamedTable().update(runtimeContext, data); } @Comment("执行update语句") public int update(RuntimeContext runtimeContext, @Comment(name = "data", value = "各项列和值") Map data, @Comment(name = "isUpdateBlank", value = "是否更新空值字段") boolean isUpdateBlank) { - return namedTable.update(runtimeContext, data, isUpdateBlank); - } - - @Comment("执行分页查询") - public Object page(RuntimeContext runtimeContext) { - return namedTable.page(runtimeContext); - } - - @Comment("执行分页查询,分页条件手动传入") - public Object page(RuntimeContext runtimeContext, - @Comment(name = "limit", value = "限制条数") long limit, - @Comment(name = "offset", value = "跳过条数") long offset) { - return namedTable.page(runtimeContext, limit, offset); - } - - @Comment("执行select查询") - public List> select(RuntimeContext runtimeContext) { - return namedTable.select(runtimeContext); - } - - @Comment("执行selectOne查询") - public Map selectOne(RuntimeContext runtimeContext) { - return namedTable.selectOne(runtimeContext); - } - - @Comment("查询条数") - public int count(RuntimeContext runtimeContext) { - return namedTable.count(runtimeContext); - } - - @Comment("查询是否存在") - public boolean exists(RuntimeContext runtimeContext) { - return namedTable.exists(runtimeContext); - } - - @Transient - public void appendAnd() { - remove(); - tokens.add("and"); - } - - @Transient - public void appendOr() { - remove(); - tokens.add("or"); + return getNamedTable().update(runtimeContext, data, isUpdateBlank); } - List getParams() { - return params; - } - - void remove() { - int size = tokens.size(); - while (size > 0) { - String token = tokens.get(size - 1); - if ("and".equalsIgnoreCase(token) || "or".equalsIgnoreCase(token)) { - tokens.remove(size - 1); - size--; - } else { - break; - } - } - while (size > 0) { - String token = tokens.get(0); - if ("and".equalsIgnoreCase(token) || "or".equalsIgnoreCase(token)) { - tokens.remove(0); - size--; - } else { - break; - } - } - } - - boolean isEmpty() { - return tokens.isEmpty(); - } - - @Transient - public void append(String value) { - tokens.add(value); - } - - @Transient - public void append(String sql, Object value) { - tokens.add(sql); - params.add(value); - } - - String getSql() { + @Override + protected String getSql() { remove(); if (isEmpty()) { return ""; } return (needWhere ? " where " : "") + String.join(" ", tokens); } - - boolean filterNullAndBlank(Object value) { - if (notNull && value == null) { - return false; - } - return !notBlank || !StringUtils.isEmpty(Objects.toString(value, "")); - } - - private Where append(boolean append, String column, String condition, Object value) { - if (append && filterNullAndBlank(value)) { - append(namedTable.rowMapColumnMapper.apply(column)); - append(condition); - appendAnd(); - params.add(value); - } - return this; - } } diff --git a/magic-api/src/main/java/org/ssssssss/magicapi/modules/db/table/WhereBase.java b/magic-api/src/main/java/org/ssssssss/magicapi/modules/db/table/WhereBase.java new file mode 100644 index 00000000..29e50145 --- /dev/null +++ b/magic-api/src/main/java/org/ssssssss/magicapi/modules/db/table/WhereBase.java @@ -0,0 +1,658 @@ +package org.ssssssss.magicapi.modules.db.table; + +import org.apache.commons.lang3.NotImplementedException; +import org.apache.commons.lang3.StringUtils; +import org.ssssssss.script.annotation.Comment; +import org.ssssssss.script.functions.StreamExtension; + +import java.beans.Transient; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Objects; +import java.util.function.Function; + +/** + * 表API的Where基类 + * + * @author tom + */ +public class WhereBase { + + protected final List tokens = new ArrayList<>(); + + protected final List params = new ArrayList<>(); + + protected final TableBase tableBase; + + protected final boolean needWhere; + + protected boolean notNull = false; + + protected boolean notBlank = false; + + public WhereBase(TableBase tableBase) { + this(tableBase, true); + } + + public WhereBase(TableBase tableBase, boolean needWhere) { + this.tableBase = tableBase; + this.needWhere = needWhere; + } + + @Transient + @Comment("克隆") + public WhereBase clone() { + WhereBase whereOrOn = new WhereBase(this.tableBase, this.needWhere); + whereOrOn.tokens.addAll(this.tokens); + whereOrOn.params.addAll(this.params); + whereOrOn.notNull = this.notNull; + whereOrOn.notBlank = this.notBlank; + return whereOrOn; + } + + @Transient + @Comment("过滤`null`的参数") + public WhereBase notNull() { + return notNull(true); + } + + @Comment("过滤`blank`的参数") + public WhereBase notBlank() { + return notBlank(true); + } + + @Transient + @Comment("是否过滤`null`的参数") + WhereBase notNull(boolean flag) { + notNull = flag; + return this; + } + + @Transient + @Comment("是否过滤`blank`的参数") + WhereBase notBlank(boolean flag) { + notBlank = flag; + return this; + } + + @Transient + @Comment("使用逻辑删除") + WhereBase logic() { + tableBase.useLogic = true; + return this; + } + + @Transient + @Comment("等于`=`,如:`eq('name', '老王') ---> name = '老王'`") + WhereBase eq(@Comment(name = "column", value = "数据库中的列名") String column, + @Comment(name = "value", value = "值") Object value) { + return eq(true, column, value); + } + + @Transient + @Comment("等于`=`,如:`eq('name', '老王') ---> name = '老王'`") + WhereBase eq(@Comment(name = "condition", value = "判断表达式,当为true时拼接条件") boolean condition, + @Comment(name = "column", value = "数据库中的列名") String column, + @Comment(name = "value", value = "值") Object value) { + if (condition && filterNullAndBlank(value)) { + tokens.add(tableBase.rowMapColumnMapper.apply(column)); + if (value == null) { + append(" is null"); + } else { + params.add(value); + append(" = ?"); + } + appendAnd(); + } + return this; + } + + @Transient + @Comment("等于`=`,如:`eq2('t.userId', 'u.id') ---> t.userId = u.id`") + WhereBase eq2(@Comment(name = "column1", value = "数据库中的列名1") String column1, + @Comment(name = "column2", value = "数据库中的列名2") String column2) { + return eq2(true, column1, column2); + } + + @Transient + @Comment("等于`=`,如:`eq2('t.userId', 'u.id') ---> t.userId = u.id`") + WhereBase eq2(@Comment(name = "condition", value = "判断表达式,当为true时拼接条件") boolean condition, + @Comment(name = "column1", value = "数据库中的列名1") String column1, + @Comment(name = "column2", value = "数据库中的列名2") String column2) { + return append2(condition, column1, " = ", column2); + } + + @Transient + @Comment("不等于`<>`,如:`ne('name', '老王') ---> name <> '老王'`") + WhereBase ne(@Comment(name = "column", value = "数据库中的列名") String column, + @Comment(name = "value", value = "值") Object value) { + return ne(true, column, value); + } + + @Transient + @Comment("不等于`<>`,如:`ne('name', '老王') ---> name <> '老王'`") + WhereBase ne(@Comment(name = "condition", value = "判断表达式,当为true时拼接条件") boolean condition, + @Comment(name = "column", value = "数据库中的列名") String column, + @Comment(name = "value", value = "值") Object value) { + if (condition && filterNullAndBlank(value)) { + append(tableBase.rowMapColumnMapper.apply(column)); + if (value == null) { + append("is not null"); + } else { + params.add(value); + append("<> ?"); + } + appendAnd(); + } + return this; + } + + @Transient + @Comment("不等于`<>`,如:`ne2('t.name', 'u.name') ---> t.name <> u.name`") + WhereBase ne2(@Comment(name = "column1", value = "数据库中的列名1") String column1, + @Comment(name = "column2", value = "数据库中的列名2") String column2) { + return ne2(true, column1, column2); + } + + @Transient + @Comment("不等于`<>`,如:`ne2('t.name', 'u.name') ---> t.name <> u.name`") + WhereBase ne2(@Comment(name = "condition", value = "判断表达式,当为true时拼接条件") boolean condition, + @Comment(name = "column1", value = "数据库中的列名1") String column1, + @Comment(name = "column2", value = "数据库中的列名2") String column2) { + return append2(condition, column1, " <> ", column2); + } + + @Transient + @Comment("between('t.createTime', '2023-01-01', '2023-01-31', true, false) ---> t.create_time >= '2023-01-01' and t.create_time < '2023-01-31'") + WhereBase between( + @Comment(name = "column", value = "数据库中的列名") String column, + @Comment(name = "startVal", value = "开始值") Object startVal, + @Comment(name = "endVal", value = "结束值") Object endVal, + @Comment(name = "startContain", value = "包含开始值") boolean startContain, + @Comment(name = "endContain", value = "包含结束值") boolean endContain + ) { + return between(true,true,column,startVal,endVal,startContain,endContain); + } + + @Transient + @Comment("between(true, true, 't.createTime', '2023-01-01', '2023-01-31') ---> t.create_time >= '2023-01-01' and t.create_time <= '2023-01-31'") + WhereBase between( + @Comment(name = "startCon", value = "判断表达式,当为true时拼接条件") boolean startCon, + @Comment(name = "endCon", value = "判断表达式,当为true时拼接条件") boolean endCon, + @Comment(name = "column", value = "数据库中的列名") String column, + @Comment(name = "startVal", value = "开始值") Object startVal, + @Comment(name = "endVal", value = "结束值") Object endVal + ) { + return between(startCon,endCon,column,startVal,endVal,true,true); + } + + @Transient + @Comment("between('t.createTime', '2023-01-01', '2023-01-31') ---> t.create_time >= '2023-01-01' and t.create_time <= '2023-01-31'") + WhereBase between( + @Comment(name = "column", value = "数据库中的列名") String column, + @Comment(name = "startVal", value = "开始值") Object startVal, + @Comment(name = "endVal", value = "结束值") Object endVal + ) { + return between(true,true,column,startVal,endVal,true,true); + } + + @Transient + @Comment("between(true, true, 't.createTime', '2023-01-01', '2023-01-31', true, false) ---> t.create_time >= '2023-01-01' and t.create_time < '2023-01-31'") + WhereBase between( + @Comment(name = "startCon", value = "判断表达式,当为true时拼接条件") boolean startCon, + @Comment(name = "endCon", value = "判断表达式,当为true时拼接条件") boolean endCon, + @Comment(name = "column", value = "数据库中的列名") String column, + @Comment(name = "startVal", value = "开始值") Object startVal, + @Comment(name = "endVal", value = "结束值") Object endVal, + @Comment(name = "startContain", value = "包含开始值") boolean startContain, + @Comment(name = "endContain", value = "包含结束值") boolean endContain + ) { + append(startCon,column,startContain ? ">=" : ">",startVal).append(endCon,column,endContain ? "<=" : "<",endVal); + return this; + } + + @Transient + @Comment("等于`=`,如:`notExists(true, 'table_name', 'tn', namedWhere -> namedWhere.eq2('tn.aId','a.id').eq('tn.name','老王'), true) ---> not exists(select 1 from table_name as tn namedWhere tn.a_id=a.id and tn.user_id='老王' and tn.del_flag<>1`") + WhereBase notExists(@Comment(name = "condition", value = "判断表达式,当为true时拼接条件") boolean condition, + @Comment(name = "tableName", value = "表名") String tableName, + @Comment(name = "alias", value = "别名") String alias, + @Comment(name = "function", value = "关联条件") Function function, + @Comment(name = "useLogic", value = "使用逻辑删除") boolean useLogic) { + return exists(true, condition, tableName, alias, function, useLogic); + } + + @Transient + @Comment("等于`=`,如:`exists('table_name', 'tn', namedWhere -> namedWhere.eq2('tn.aId','a.id').eq('tn.name','老王'), true) ---> exists(select 1 from table_name as tn namedWhere tn.a_id=a.id and tn.user_id='老王' and tn.del_flag<>1`") + WhereBase notExists(@Comment(name = "tableName", value = "表名") String tableName, + @Comment(name = "alias", value = "别名") String alias, + @Comment(name = "function", value = "关联条件") Function function, + @Comment(name = "useLogic", value = "使用逻辑删除") boolean useLogic) { + return notExists(true, tableName, alias, function, useLogic); + } + + @Transient + @Comment("等于`=`,如:`exists(true, 'table_name', 'tn', namedWhere -> namedWhere.eq2('tn.aId','a.id').eq('tn.name','老王')) ---> exists(select 1 from table_name as tn namedWhere tn.a_id=a.id and tn.user_id='老王'`") + WhereBase notExists(@Comment(name = "tableName", value = "表名") String tableName, + @Comment(name = "alias", value = "别名") String alias, + @Comment(name = "function", value = "关联条件") Function function) { + return notExists(true, tableName, alias, function, false); + } + + @Transient + @Comment("等于`=`,如:`exists(true, 'table_name', 'tn', namedWhere -> namedWhere.eq2('tn.aId','a.id').eq('tn.name','老王'), true) ---> exists(select 1 from table_name as tn namedWhere tn.a_id=a.id and tn.user_id='老王' and tn.del_flag<>1`") + WhereBase exists(@Comment(name = "condition", value = "判断表达式,当为true时拼接条件") boolean condition, + @Comment(name = "tableName", value = "表名") String tableName, + @Comment(name = "alias", value = "别名") String alias, + @Comment(name = "function", value = "关联条件") Function function, + @Comment(name = "useLogic", value = "使用逻辑删除") boolean useLogic) { + return exists(false, condition, tableName, alias, function, useLogic); + } + + @Transient + @Comment("等于`=`,如:`exists('table_name', 'tn', namedWhere -> namedWhere.eq2('tn.aId','a.id').eq('tn.name','老王'), true) ---> exists(select 1 from table_name as tn namedWhere tn.a_id=a.id and tn.user_id='老王' and tn.del_flag<>1`") + WhereBase exists(@Comment(name = "tableName", value = "表名") String tableName, + @Comment(name = "alias", value = "别名") String alias, + @Comment(name = "function", value = "关联条件") Function function, + @Comment(name = "useLogic", value = "使用逻辑删除") boolean useLogic) { + return exists(true, tableName, alias, function, useLogic); + } + + @Transient + @Comment("等于`=`,如:`exists('table_name', 'tn', namedWhere -> namedWhere.eq2('tn.aId','a.id').eq('tn.name','老王')) ---> exists(select 1 from table_name as tn namedWhere tn.a_id=a.id and tn.user_id='老王'`") + WhereBase exists(@Comment(name = "tableName", value = "表名") String tableName, + @Comment(name = "alias", value = "别名") String alias, + @Comment(name = "function", value = "关联条件") Function function) { + return exists(true, tableName, alias, function, false); + } + + @Comment("存在子查询") + WhereBase exists(boolean notFlag, boolean condition, String tableName, String alias, + Function function, + boolean useLogic) { + if (condition) { + if (notFlag) { + append("not"); + } + append("exists(select 1 from"); + append(tableName); + if (StringUtils.isNotEmpty(alias)) { + append("as"); + append(alias); + } + WhereBase whereBase = new WhereBase(tableBase); + function.apply(whereBase); + if (!whereBase.isEmpty()) { + whereBase.and(); + } + whereBase.ne(useLogic, + (StringUtils.isNotEmpty(alias) ? (alias + ".") : "") + tableBase.logicDeleteColumn, + tableBase.logicDeleteValue); + append(whereBase.getSql()); + params.addAll(whereBase.getParams()); + append(")"); + appendAnd(); + } + return this; + } + + @Transient + @Comment("小于`<`,如:`lt('age', 18) ---> age < 18") + WhereBase lt(@Comment(name = "column", value = "数据库中的列名") String column, + @Comment(name = "value", value = "值") Object value) { + return lt(true, column, value); + } + + @Transient + @Comment("小于`<`,如:`lt('age', 18) ---> age < 18") + WhereBase lt(@Comment(name = "condition", value = "判断表达式,当为true时拼接条件") boolean condition, + @Comment(name = "column", value = "数据库中的列名") String column, + @Comment(name = "value", value = "值") Object value) { + return append(condition, column, " < ?", value); + } + + @Transient + @Comment("小于`<`,如:`lt2('t.age', 'u.age') ---> t.age < u.age") + WhereBase lt2(@Comment(name = "column1", value = "数据库中的列名1") String column1, + @Comment(name = "column2", value = "数据库中的列名2") String column2) { + return lt2(true, column1, column2); + } + + @Transient + @Comment("小于`<`,如:`lt2('t.age', 'u.age') ---> t.age < u.age") + WhereBase lt2(@Comment(name = "condition", value = "判断表达式,当为true时拼接条件") boolean condition, + @Comment(name = "column1", value = "数据库中的列名1") String column1, + @Comment(name = "column2", value = "数据库中的列名2") String column2) { + return append2(condition, column1, " < ", column2); + } + + @Transient + @Comment("小于等于`<=`,如:`lte('age', 18) ---> age <= 18") + WhereBase lte(@Comment(name = "column", value = "数据库中的列名") String column, + @Comment(name = "value", value = "值") Object value) { + return lte(true, column, value); + } + + @Transient + @Comment("小于等于`<=`,如:`lte('age', 18) ---> age <= 18") + WhereBase lte(@Comment(name = "condition", value = "判断表达式,当为true时拼接条件") boolean condition, + @Comment(name = "column", value = "数据库中的列名") String column, + @Comment(name = "value", value = "值") Object value) { + return append(condition, column, " <= ?", value); + } + + @Transient + @Comment("小于等于`<=`,如:`lte2('t.age', 'u.age') ---> t.age <= u.age") + WhereBase lte2(@Comment(name = "column1", value = "数据库中的列名1") String column1, + @Comment(name = "column2", value = "数据库中的列名2") String column2) { + return lte2(true, column1, column2); + } + + @Transient + @Comment("小于等于`<=`,如:`lte2('t.age', 'u.age') ---> t.age <= u.age") + WhereBase lte2(@Comment(name = "condition", value = "判断表达式,当为true时拼接条件") boolean condition, + @Comment(name = "column1", value = "数据库中的列名1") String column1, + @Comment(name = "column2", value = "数据库中的列名2") String column2) { + return append2(condition, column1, " <= ", column2); + } + + @Transient + @Comment("大于`>`,如:`get('age', 18) ---> age > 18") + WhereBase gt(@Comment(name = "column", value = "数据库中的列名") String column, + @Comment(name = "value", value = "值") Object value) { + return gt(true, column, value); + } + + @Transient + @Comment("大于`>`,如:`get('age', 18) ---> age > 18") + WhereBase gt(@Comment(name = "condition", value = "判断表达式,当为true时拼接条件") boolean condition, + @Comment(name = "column", value = "数据库中的列名") String column, + @Comment(name = "value", value = "值") Object value) { + return append(condition, column, " > ?", value); + } + + @Transient + @Comment("大于`>`,如:`get('t.age', 't.age') ---> t.age > u.age") + WhereBase gt2(@Comment(name = "column1", value = "数据库中的列名1") String column1, + @Comment(name = "column2", value = "数据库中的列名2") String column2) { + return gt2(true, column1, column2); + } + + @Transient + @Comment("大于`>`,如:`get('t.age', 't.age') ---> t.age > u.age") + WhereBase gt2(@Comment(name = "condition", value = "判断表达式,当为true时拼接条件") boolean condition, + @Comment(name = "column1", value = "数据库中的列名1") String column1, + @Comment(name = "column2", value = "数据库中的列名2") String column2) { + return append2(condition, column1, " > ", column2); + } + + @Transient + @Comment("大于等于`>=`,如:`get('age', 18) ---> age >= 18") + WhereBase gte(@Comment(name = "column", value = "数据库中的列名") String column, + @Comment(name = "value", value = "值") Object value) { + return gte(true, column, value); + } + + @Transient + @Comment("大于等于`>=`,如:`get('age', 18) ---> age >= 18") + WhereBase gte(@Comment(name = "condition", value = "判断表达式,当为true时拼接条件") boolean condition, + @Comment(name = "column", value = "数据库中的列名") String column, + @Comment(name = "value", value = "值") Object value) { + return append(condition, column, " >= ?", value); + } + + @Transient + @Comment("大于等于`>=`,如:`get('t.age', 'u.age') ---> t.age >= u.age") + WhereBase gte2(@Comment(name = "column1", value = "数据库中的列名1") String column1, + @Comment(name = "column2", value = "数据库中的列名2") String column2) { + return gte2(true, column1, column2); + } + + @Transient + @Comment("大于等于`>=`,如:`get('t.age', 'u.age') ---> t.age >= u.age") + WhereBase gte2(@Comment(name = "condition", value = "判断表达式,当为true时拼接条件") boolean condition, + @Comment(name = "column1", value = "数据库中的列名1") String column1, + @Comment(name = "column2", value = "数据库中的列名2") String column2) { + return append2(condition, column1, " >= ", column2); + } + + @Transient + @Comment("`in`,如:`in('age', [1,2,3]) ---> age in (1,2,3)") + WhereBase in(@Comment(name = "column", value = "数据库中的列名") String column, + @Comment(name = "value", value = "值") Object value) { + return in(true, column, value); + } + + @Transient + @Comment("`in`,如:`in('age', [1,2,3]) ---> age in (1,2,3)") + WhereBase in(@Comment(name = "condition", value = "判断表达式,当为true时拼接条件") boolean condition, + @Comment(name = "column", value = "数据库中的列名") String column, + @Comment(name = "value", value = "值") Object value) { + if (condition && value != null) { + List objects = StreamExtension.arrayLikeToList(value); + if (objects.size() > 0) { + append(tableBase.rowMapColumnMapper.apply(column)); + append(" in ("); + append(String.join(",", Collections.nCopies(objects.size(), "?"))); + append(")"); + appendAnd(); + params.addAll(objects); + } + } + return this; + } + + @Transient + @Comment("`not in`,如:`notIn('age', [1,2,3]) ---> age not in (1,2,3)") + WhereBase notIn(@Comment(name = "column", value = "数据库中的列名") String column, + @Comment(name = "value", value = "值") Object value) { + return notIn(true, column, value); + } + + @Transient + @Comment("`not in`,如:`notIn('age', [1,2,3]) ---> age not in (1,2,3)") + WhereBase notIn(@Comment(name = "condition", value = "判断表达式,当为true时拼接条件") boolean condition, + @Comment(name = "column", value = "数据库中的列名") String column, + @Comment(name = "value", value = "值") Object value) { + if (condition && value != null) { + List objects = StreamExtension.arrayLikeToList(value); + if (objects.size() > 0) { + append(tableBase.rowMapColumnMapper.apply(column)); + append("not in ("); + append(String.join(",", Collections.nCopies(objects.size(), "?"))); + append(")"); + appendAnd(); + params.addAll(objects); + } + } + return this; + } + + @Transient + @Comment("`like`,如:`like('name', '%王%') ---> name like '%王%'") + WhereBase like(@Comment(name = "column", value = "数据库中的列名") String column, + @Comment(name = "value", value = "值") Object value) { + return like(true, column, value); + } + + @Transient + @Comment("`like`,如:`like('name', '%王%') ---> name like '%王%'") + WhereBase like(@Comment(name = "condition", value = "判断表达式,当为true时拼接条件") boolean condition, + @Comment(name = "column", value = "数据库中的列名") String column, + @Comment(name = "value", value = "值") Object value) { + return append(condition, column, "like ?", value); + } + + @Transient + @Comment("`not like`,如:`notLike('name', '%王%') ---> name not like '%王%'") + WhereBase notLike(@Comment(name = "column", value = "数据库中的列名") String column, + @Comment(name = "value", value = "值") Object value) { + return notLike(true, column, value); + } + + @Transient + @Comment("`not like` ,如:`notLike('name', '%王%') ---> name not like '%王%'") + WhereBase notLike(@Comment(name = "condition", value = "判断表达式,当为true时拼接条件") boolean condition, + @Comment(name = "column", value = "数据库中的列名") String column, + @Comment(name = "value", value = "值") Object value) { + return append(condition, column, "not like ?", value); + } + + @Transient + @Comment("`is null`,如:`isNull('name') ---> name is null") + WhereBase isNull(@Comment(name = "column", value = "数据库中的列名") String column) { + return isNull(true, column); + } + + @Transient + @Comment("`is null`,如:`isNull('name') ---> name is null") + WhereBase isNull(@Comment(name = "condition", value = "判断表达式,当为true时拼接条件") boolean condition, + @Comment(name = "column", value = "数据库中的列名") String column) { + if (condition) { + append(tableBase.rowMapColumnMapper.apply(column)); + append("is null"); + appendAnd(); + } + return this; + } + + @Transient + @Comment("`is not null`,如:`isNotNull('name') ---> name is not null") + WhereBase isNotNull(@Comment(name = "column", value = "数据库中的列名") String column) { + return isNotNull(true, column); + } + + @Transient + @Comment("`is not null`,如:`isNotNull('name') ---> name is not null") + WhereBase isNotNull(@Comment(name = "condition", value = "判断表达式,当为true时拼接条件") boolean condition, + @Comment(name = "column", value = "数据库中的列名") String column) { + if (condition) { + append(tableBase.rowMapColumnMapper.apply(column)); + append("is not null"); + appendAnd(); + } + return this; + } + + @Transient + @Comment("拼接`or`") + WhereBase or() { + appendOr(); + return this; + } + + @Transient + @Comment("拼接`and`") + WhereBase and() { + appendAnd(); + return this; + } + + @Transient + @Comment("`and`嵌套,如and(it => it.eq('name','李白').ne('status','正常') --> and (name = '李白' and status <> '正常')") + WhereBase and(@Comment(name = "function", value = "回调函数") Function function) { + return and(true, function); + } + + @Transient + @Comment("`and`嵌套,如and(it => it.eq('name','李白').ne('status','正常') --> and (name = '李白' and status <> '正常')") + WhereBase and(@Comment(name = "condition", value = "判断表达式,当为true时拼接条件") boolean condition, + @Comment(name = "function", value = "回调函数") Function function) { + if (condition) { + WhereBase expr = function.apply(new Object[]{new WhereBase(this.tableBase, false)}); + this.params.addAll(expr.params); + String sql = expr.getSql(); + if (StringUtils.isNotBlank(sql)) { + append("("); + append(sql); + append(")"); + appendAnd(); + } + } + return this; + } + + @Transient + void appendAnd() { + remove(); + tokens.add("and"); + } + + @Transient + void appendOr() { + remove(); + tokens.add("or"); + } + + List getParams() { + return params; + } + + void remove() { + int size = tokens.size(); + while (size > 0) { + String token = tokens.get(size - 1); + if ("and".equalsIgnoreCase(token) || "or".equalsIgnoreCase(token)) { + tokens.remove(size - 1); + size--; + } else { + break; + } + } + while (size > 0) { + String token = tokens.get(0); + if ("and".equalsIgnoreCase(token) || "or".equalsIgnoreCase(token)) { + tokens.remove(0); + size--; + } else { + break; + } + } + } + + boolean isEmpty() { + return tokens.isEmpty(); + } + + @Transient + void append(String value) { + tokens.add(value); + } + + @Transient + void append(String sql, Object value) { + tokens.add(sql); + params.add(value); + } + + protected String getSql() { + throw new NotImplementedException("获取sql方法未实现!"); + } + + boolean filterNullAndBlank(Object value) { + if (notNull && value == null) { + return false; + } + return !notBlank || !StringUtils.isEmpty(Objects.toString(value, "")); + } + + WhereBase append(boolean append, String column, String condition, Object value) { + if (append && filterNullAndBlank(value)) { + append(tableBase.rowMapColumnMapper.apply(column)); + append(condition); + appendAnd(); + params.add(value); + } + return this; + } + + WhereBase append2(boolean append, String column1, String condition, String column2) { + if (append) { + append(tableBase.rowMapColumnMapper.apply(column1)); + append(condition); + append(tableBase.rowMapColumnMapper.apply(column2)); + appendAnd(); + } + return this; + } +} -- Gitee From 5078d8f11d12eddcd7b3fd93cd8f99531fa6415d Mon Sep 17 00:00:00 2001 From: leheyue Date: Thu, 21 Sep 2023 14:38:45 +0800 Subject: [PATCH 2/4] =?UTF-8?q?db=E6=A8=A1=E5=9D=97=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E8=A1=A8=E8=BF=9E=E6=8E=A5=E6=8E=A5=E5=8F=A3=E5=92=8C=E6=98=A0?= =?UTF-8?q?=E5=B0=84=E5=AD=97=E6=AE=B5=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../org/ssssssss/magicapi/modules/db/table/WhereBase.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/magic-api/src/main/java/org/ssssssss/magicapi/modules/db/table/WhereBase.java b/magic-api/src/main/java/org/ssssssss/magicapi/modules/db/table/WhereBase.java index 29e50145..73fa17ba 100644 --- a/magic-api/src/main/java/org/ssssssss/magicapi/modules/db/table/WhereBase.java +++ b/magic-api/src/main/java/org/ssssssss/magicapi/modules/db/table/WhereBase.java @@ -223,7 +223,7 @@ public class WhereBase { } @Transient - @Comment("等于`=`,如:`exists('table_name', 'tn', namedWhere -> namedWhere.eq2('tn.aId','a.id').eq('tn.name','老王'), true) ---> exists(select 1 from table_name as tn namedWhere tn.a_id=a.id and tn.user_id='老王' and tn.del_flag<>1`") + @Comment("等于`=`,如:`notExists('table_name', 'tn', namedWhere -> namedWhere.eq2('tn.aId','a.id').eq('tn.name','老王'), true) ---> not exists(select 1 from table_name as tn namedWhere tn.a_id=a.id and tn.user_id='老王' and tn.del_flag<>1`") WhereBase notExists(@Comment(name = "tableName", value = "表名") String tableName, @Comment(name = "alias", value = "别名") String alias, @Comment(name = "function", value = "关联条件") Function function, @@ -232,7 +232,7 @@ public class WhereBase { } @Transient - @Comment("等于`=`,如:`exists(true, 'table_name', 'tn', namedWhere -> namedWhere.eq2('tn.aId','a.id').eq('tn.name','老王')) ---> exists(select 1 from table_name as tn namedWhere tn.a_id=a.id and tn.user_id='老王'`") + @Comment("等于`=`,如:`notExists(true, 'table_name', 'tn', namedWhere -> namedWhere.eq2('tn.aId','a.id').eq('tn.name','老王')) ---> not exists(select 1 from table_name as tn namedWhere tn.a_id=a.id and tn.user_id='老王'`") WhereBase notExists(@Comment(name = "tableName", value = "表名") String tableName, @Comment(name = "alias", value = "别名") String alias, @Comment(name = "function", value = "关联条件") Function function) { @@ -430,7 +430,7 @@ public class WhereBase { @Comment(name = "value", value = "值") Object value) { if (condition && value != null) { List objects = StreamExtension.arrayLikeToList(value); - if (objects.size() > 0) { + if (!objects.isEmpty()) { append(tableBase.rowMapColumnMapper.apply(column)); append(" in ("); append(String.join(",", Collections.nCopies(objects.size(), "?"))); @@ -456,7 +456,7 @@ public class WhereBase { @Comment(name = "value", value = "值") Object value) { if (condition && value != null) { List objects = StreamExtension.arrayLikeToList(value); - if (objects.size() > 0) { + if (!objects.isEmpty()) { append(tableBase.rowMapColumnMapper.apply(column)); append("not in ("); append(String.join(",", Collections.nCopies(objects.size(), "?"))); -- Gitee From cfaa010eb2c1f2808593f0abe801af60d654d9de Mon Sep 17 00:00:00 2001 From: leheyue Date: Fri, 22 Sep 2023 14:10:15 +0800 Subject: [PATCH 3/4] =?UTF-8?q?=E5=88=86=E9=A1=B5=E7=BB=93=E6=9E=9C?= =?UTF-8?q?=E6=9E=84=E5=BB=BA=E6=8E=A5=E5=8F=A3=E8=BF=98=E5=8E=9F=E4=B8=BA?= =?UTF-8?q?Object=EF=BC=8C=E4=BB=A5=E5=85=BC=E5=AE=B9=E8=87=AA=E5=AE=9A?= =?UTF-8?q?=E4=B9=89=E5=88=86=E9=A1=B5=E6=8E=A5=E5=8F=A3=E6=9E=84=E5=BB=BA?= =?UTF-8?q?=EF=BC=9B=E5=B0=86=E6=95=B0=E6=8D=AE=E5=BA=93=E6=9F=A5=E8=AF=A2?= =?UTF-8?q?=E6=A8=A1=E5=9D=97=E7=9A=84=E5=88=86=E9=A1=B5=E6=8E=A5=E5=8F=A3?= =?UTF-8?q?=E6=8B=86=E5=88=86=E4=B8=BA=E6=9F=A5=E8=AF=A2=E5=88=86=E9=A1=B5?= =?UTF-8?q?=E6=95=B0=E6=8D=AE=E5=8F=8A=E6=9E=84=E5=BB=BA=E5=88=86=E9=A1=B5?= =?UTF-8?q?=E7=BB=93=E6=9E=9C=E4=B8=A4=E4=B8=AA=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../core/interceptor/ResultProvider.java | 4 +- .../magicapi/modules/db/SQLModule.java | 36 +++++++++-- .../modules/db/model/PageResultBuilder.java | 59 +++++++++++++++++++ .../magicapi/modules/db/table/NamedTable.java | 18 +++--- .../modules/db/table/TableInterface.java | 5 +- 5 files changed, 103 insertions(+), 19 deletions(-) create mode 100644 magic-api/src/main/java/org/ssssssss/magicapi/modules/db/model/PageResultBuilder.java diff --git a/magic-api/src/main/java/org/ssssssss/magicapi/core/interceptor/ResultProvider.java b/magic-api/src/main/java/org/ssssssss/magicapi/core/interceptor/ResultProvider.java index da3be5a6..10302d94 100644 --- a/magic-api/src/main/java/org/ssssssss/magicapi/core/interceptor/ResultProvider.java +++ b/magic-api/src/main/java/org/ssssssss/magicapi/core/interceptor/ResultProvider.java @@ -2,9 +2,9 @@ package org.ssssssss.magicapi.core.interceptor; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.ssssssss.magicapi.core.context.RequestEntity; import org.ssssssss.magicapi.modules.db.model.Page; import org.ssssssss.magicapi.modules.db.model.PageResult; -import org.ssssssss.magicapi.core.context.RequestEntity; import org.ssssssss.script.exception.MagicScriptAssertException; import org.ssssssss.script.exception.MagicScriptException; import org.ssssssss.script.functions.ObjectConvertExtension; @@ -105,7 +105,7 @@ public interface ResultProvider { * @param total 总数 * @param data 数据内容 */ - default PageResult buildPageResult(RequestEntity requestEntity, Page page, long total, List> data) { + default Object buildPageResult(RequestEntity requestEntity, Page page, long total, List> data) { return new PageResult<>(total, data); } diff --git a/magic-api/src/main/java/org/ssssssss/magicapi/modules/db/SQLModule.java b/magic-api/src/main/java/org/ssssssss/magicapi/modules/db/SQLModule.java index 04b9d57f..83bcf0c6 100644 --- a/magic-api/src/main/java/org/ssssssss/magicapi/modules/db/SQLModule.java +++ b/magic-api/src/main/java/org/ssssssss/magicapi/modules/db/SQLModule.java @@ -17,7 +17,7 @@ import org.ssssssss.magicapi.modules.db.dialect.DialectAdapter; import org.ssssssss.magicapi.modules.db.inteceptor.NamedTableInterceptor; import org.ssssssss.magicapi.modules.db.inteceptor.SQLInterceptor; import org.ssssssss.magicapi.modules.db.model.Page; -import org.ssssssss.magicapi.modules.db.model.PageResult; +import org.ssssssss.magicapi.modules.db.model.PageResultBuilder; import org.ssssssss.magicapi.modules.db.model.SqlTypes; import org.ssssssss.magicapi.modules.db.provider.PageProvider; import org.ssssssss.magicapi.modules.db.table.NamedTable; @@ -551,11 +551,17 @@ public class SQLModule implements DynamicAttribute, Dynami } @Transient - public PageResult page(BoundSql boundSql) { + public Object page(BoundSql boundSql) { Page page = pageProvider.getPage(boundSql.getRuntimeContext()); return page(boundSql, page); } + @Transient + public PageResultBuilder> executePage(BoundSql boundSql) { + Page page = pageProvider.getPage(boundSql.getRuntimeContext()); + return executePage(boundSql, page); + } + @Transient public String getDataSourceName() { return this.dataSourceNode == null ? "unknown" : dataSourceNode.getName(); @@ -599,7 +605,12 @@ public class SQLModule implements DynamicAttribute, Dynami return page(count, boundSql, new Page(limit, offset), null); } - private PageResult page(int count, BoundSql boundSql, Page page, Dialect dialect) { + private Object page(int count, BoundSql boundSql, Page page, Dialect dialect) { + return buildPageResult(executePage(count, boundSql, page, dialect)); + } + + @Transient + public PageResultBuilder> executePage(int count, BoundSql boundSql, Page page, Dialect dialect) { List> list = null; if (count > 0) { if (dialect == null) { @@ -608,12 +619,18 @@ public class SQLModule implements DynamicAttribute, Dynami BoundSql pageBoundSql = buildPageBoundSql(dialect, boundSql, page.getOffset(), page.getLimit()); list = pageBoundSql.execute(this.sqlInterceptors, () -> queryForList(pageBoundSql)); } + + return new PageResultBuilder<>(page, count, list); + } + + @Transient + public Object buildPageResult(PageResultBuilder> builder) { RequestEntity requestEntity = RequestContext.getRequestEntity(); - return resultProvider.buildPageResult(requestEntity, page, count, list); + return resultProvider.buildPageResult(requestEntity, builder.getPage(), builder.getTotal(), builder.getList()); } @Transient - public PageResult page(BoundSql boundSql, Page page) { + public Object page(BoundSql boundSql, Page page) { assertDatasourceNotNull(); Dialect dialect = dataSourceNode.getDialect(dialectAdapter); BoundSql countBoundSql = boundSql.copy(dialect.getCountSql(boundSql.getSql())); @@ -621,6 +638,15 @@ public class SQLModule implements DynamicAttribute, Dynami return page(count, boundSql, page, dialect); } + @Transient + public PageResultBuilder> executePage(BoundSql boundSql, Page page) { + assertDatasourceNotNull(); + Dialect dialect = dataSourceNode.getDialect(dialectAdapter); + BoundSql countBoundSql = boundSql.copy(dialect.getCountSql(boundSql.getSql())); + int count = selectInt(countBoundSql); + return executePage(count, boundSql, page, dialect); + } + /** * 查询总条目数 */ diff --git a/magic-api/src/main/java/org/ssssssss/magicapi/modules/db/model/PageResultBuilder.java b/magic-api/src/main/java/org/ssssssss/magicapi/modules/db/model/PageResultBuilder.java new file mode 100644 index 00000000..811d60be --- /dev/null +++ b/magic-api/src/main/java/org/ssssssss/magicapi/modules/db/model/PageResultBuilder.java @@ -0,0 +1,59 @@ +package org.ssssssss.magicapi.modules.db.model; + +import java.util.List; + +/** + * 分页执行结果 + * + * @author mxd + */ +public class PageResultBuilder { + + /** + * 分页请求参数 + */ + private Page page; + + /** + * 总条数 + */ + private long total; + + /** + * 数据项 + */ + private List list; + + public PageResultBuilder(Page page, long total, List list) { + this.page = page; + this.total = total; + this.list = list; + } + + public PageResultBuilder() { + } + + public Page getPage() { + return page; + } + + public void setPage(Page page) { + this.page = page; + } + + public long getTotal() { + return total; + } + + public void setTotal(long total) { + this.total = total; + } + + public List getList() { + return list; + } + + public void setList(List list) { + this.list = list; + } +} diff --git a/magic-api/src/main/java/org/ssssssss/magicapi/modules/db/table/NamedTable.java b/magic-api/src/main/java/org/ssssssss/magicapi/modules/db/table/NamedTable.java index 9942d5ec..063f0006 100644 --- a/magic-api/src/main/java/org/ssssssss/magicapi/modules/db/table/NamedTable.java +++ b/magic-api/src/main/java/org/ssssssss/magicapi/modules/db/table/NamedTable.java @@ -10,7 +10,7 @@ import org.ssssssss.magicapi.modules.db.BoundSql; import org.ssssssss.magicapi.modules.db.SQLModule; import org.ssssssss.magicapi.modules.db.inteceptor.NamedTableInterceptor; import org.ssssssss.magicapi.modules.db.model.Page; -import org.ssssssss.magicapi.modules.db.model.PageResult; +import org.ssssssss.magicapi.modules.db.model.PageResultBuilder; import org.ssssssss.magicapi.modules.db.model.SqlMode; import org.ssssssss.script.annotation.Comment; import org.ssssssss.script.runtime.RuntimeContext; @@ -464,21 +464,21 @@ public class NamedTable extends TableBase implements JoinInterface { } @Comment("执行分页查询") - public PageResult page(RuntimeContext runtimeContext) { + public Object page(RuntimeContext runtimeContext) { preHandle(SqlMode.PAGE); - PageResult pageResult = sqlModule.page(buildSelect(runtimeContext)); - mapperResults(runtimeContext, pageResult.getList()); - return pageResult; + PageResultBuilder> pageResultBuilder = sqlModule.executePage(buildSelect(runtimeContext)); + mapperResults(runtimeContext, pageResultBuilder.getList()); + return sqlModule.buildPageResult(pageResultBuilder); } @Comment("执行分页查询,分页条件手动传入") - public PageResult page(RuntimeContext runtimeContext, + public Object page(RuntimeContext runtimeContext, @Comment(name = "limit", value = "限制条数") long limit, @Comment(name = "offset", value = "跳过条数") long offset) { preHandle(SqlMode.PAGE); - PageResult pageResult = sqlModule.page(buildSelect(runtimeContext), new Page(limit, offset)); - mapperResults(runtimeContext, pageResult.getList()); - return pageResult; + PageResultBuilder> pageResultBuilder = sqlModule.executePage(buildSelect(runtimeContext), new Page(limit, offset)); + mapperResults(runtimeContext, pageResultBuilder.getList()); + return sqlModule.buildPageResult(pageResultBuilder); } @Comment("执行update语句") diff --git a/magic-api/src/main/java/org/ssssssss/magicapi/modules/db/table/TableInterface.java b/magic-api/src/main/java/org/ssssssss/magicapi/modules/db/table/TableInterface.java index e3cd5667..cea6615b 100644 --- a/magic-api/src/main/java/org/ssssssss/magicapi/modules/db/table/TableInterface.java +++ b/magic-api/src/main/java/org/ssssssss/magicapi/modules/db/table/TableInterface.java @@ -1,6 +1,5 @@ package org.ssssssss.magicapi.modules.db.table; -import org.ssssssss.magicapi.modules.db.model.PageResult; import org.ssssssss.script.annotation.Comment; import org.ssssssss.script.runtime.RuntimeContext; @@ -42,12 +41,12 @@ public interface TableInterface { } @Comment("执行分页查询") - default PageResult page(RuntimeContext runtimeContext) { + default Object page(RuntimeContext runtimeContext) { return getNamedTable().page(runtimeContext); } @Comment("执行分页查询,分页条件手动传入") - default PageResult page(RuntimeContext runtimeContext, + default Object page(RuntimeContext runtimeContext, @Comment(name = "limit", value = "限制条数") long limit, @Comment(name = "offset", value = "跳过条数") long offset) { return getNamedTable().page(runtimeContext, limit, offset); -- Gitee From 7a466c37aa3e37e1e8055d7abf25701fa016a50f Mon Sep 17 00:00:00 2001 From: leheyue Date: Mon, 25 Sep 2023 09:43:00 +0800 Subject: [PATCH 4/4] =?UTF-8?q?=E7=A7=BB=E9=99=A4=E5=AD=97=E6=AE=B5?= =?UTF-8?q?=E6=98=A0=E5=B0=84=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../magicapi/modules/db/table/NamedTable.java | 96 +------------------ 1 file changed, 2 insertions(+), 94 deletions(-) diff --git a/magic-api/src/main/java/org/ssssssss/magicapi/modules/db/table/NamedTable.java b/magic-api/src/main/java/org/ssssssss/magicapi/modules/db/table/NamedTable.java index 063f0006..f1872026 100644 --- a/magic-api/src/main/java/org/ssssssss/magicapi/modules/db/table/NamedTable.java +++ b/magic-api/src/main/java/org/ssssssss/magicapi/modules/db/table/NamedTable.java @@ -1,8 +1,6 @@ package org.ssssssss.magicapi.modules.db.table; -import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.StringUtils; -import org.springframework.util.CollectionUtils; import org.ssssssss.magicapi.core.context.RequestContext; import org.ssssssss.magicapi.core.context.RequestEntity; import org.ssssssss.magicapi.core.exception.MagicAPIException; @@ -49,8 +47,6 @@ public class NamedTable extends TableBase implements JoinInterface { List joinedTables = new ArrayList<>(); - List mappedTables = new ArrayList<>(); - public NamedTable(String tableName, String alias, SQLModule sqlModule, Function rowMapColumnMapper, List namedTableInterceptors) { super(tableName, alias, sqlModule, rowMapColumnMapper, namedTableInterceptors); } @@ -67,7 +63,6 @@ public class NamedTable extends TableBase implements JoinInterface { namedTable.groups = new ArrayList<>(groups); namedTable.orders = new ArrayList<>(orders); namedTable.joinedTables = new ArrayList<>(joinedTables); - namedTable.mappedTables = new ArrayList<>(mappedTables); namedTable.excludeColumns = new HashSet<>(excludeColumns); namedTable.rowMapColumnMapper = this.rowMapColumnMapper; namedTable.defaultPrimaryValue = this.defaultPrimaryValue; @@ -90,59 +85,6 @@ public class NamedTable extends TableBase implements JoinInterface { return join; } - @Comment("字段映射") - public NamedTable mapping(@Comment(name = "condition", value = "判断表达式,当为true时拼接条件") boolean condition, - @Comment(name = "tableName", value = "映射表名") String tableName, - @Comment(name = "keyProperty", value = "映射主键属性") String keyProperty, - @Comment(name = "property", value = "源属性") String property, - @Comment(name = "properties", value = "映射属性集合") String... properties) { - if (condition) { - NamedTable map = new NamedTable(tableName, null, sqlModule, rowMapColumnMapper, namedTableInterceptors); - map.column(keyProperty).columns(properties); - map.where.tokens.add(keyProperty); - map.where.params.add(property); - mappedTables.add(map); - } - return this; - } - - @Comment("字段映射") - public NamedTable mapping(@Comment(name = "tableName", value = "映射表名") String tableName, - @Comment(name = "keyProperty", value = "映射主键属性") String keyProperty, - @Comment(name = "property", value = "源属性") String property, - @Comment(name = "properties", value = "映射字段集合") String... properties) { - return mapping(true, tableName, keyProperty, property, properties); - } - - @Comment("字典映射") - public NamedTable dict(@Comment(name = "condition", value = "判断表达式,当为true时拼接条件") boolean condition, - @Comment(name = "tableName", value = "字典项表名") String tableName, - @Comment(name = "typeProperty", value = "字典类型属性") String typeProperty, - @Comment(name = "typeValue", value = "字典类型值") String typeValue, - @Comment(name = "valueProperty", value = "查询字典项属性") String valueProperty, - @Comment(name = "property", value = "源属性") String property, - @Comment(name = "properties", value = "映射字段集合") String... properties) { - if (condition) { - NamedTable map = new NamedTable(tableName, null, sqlModule, rowMapColumnMapper, namedTableInterceptors); - map.column(valueProperty).columns(properties); - map.where.tokens.add(valueProperty); - map.where.params.add(property); - map.where.eq(typeProperty, typeValue); - mappedTables.add(map); - } - return this; - } - - @Comment("字典映射") - public NamedTable dict(@Comment(name = "tableName", value = "字典项表名") String tableName, - @Comment(name = "typeProperty", value = "字典类型字段") String typeProperty, - @Comment(name = "typeValue", value = "字典类型值") String typeValue, - @Comment(name = "valueProperty", value = "查询字典项字段") String valueProperty, - @Comment(name = "property", value = "源属性") String property, - @Comment(name = "properties", value = "映射字段集合") String... properties) { - return dict(true, tableName, typeProperty, typeValue, valueProperty, property, properties); - } - @Comment("使用去重") public NamedTable distinct() { this.useDistinct = true; @@ -419,55 +361,22 @@ public class NamedTable extends TableBase implements JoinInterface { return batchInsert(collection, 100); } - private void mapperResults(RuntimeContext runtimeContext, List> results) { - if (CollectionUtils.isEmpty(results)) { - return; - } - for (NamedTable mappedTable : mappedTables) { - Object property = mappedTable.where.params.get(0); - List> mapResults = results.stream() - .filter(x -> ObjectUtils.isNotEmpty(x.get(property))).collect(Collectors.toList()); - if (CollectionUtils.isEmpty(mapResults)) { - continue; - } - String field = mappedTable.where.tokens.get(0); - mappedTable.where.tokens.remove(0); - mappedTable.where.params.remove(0); - mappedTable.where.in(field, mapResults.stream().map(x -> x.get(property)).distinct().collect(Collectors.toList())); - Map> mappedMap = mappedTable.select(runtimeContext).stream() - .collect(Collectors.toMap(x -> x.get(field), x -> { - x.remove(field); - return x; - }, (x, y) -> x)); - mapResults.stream().forEach(x -> { - if (mappedMap.containsKey(x.get(property))) { - x.putAll(mappedMap.get(x.get(property))); - } - }); - } - } - @Comment("执行`select`查询") public List> select(RuntimeContext runtimeContext) { preHandle(SqlMode.SELECT); - List> results = sqlModule.select(buildSelect(runtimeContext)); - mapperResults(runtimeContext, results); - return results; + return sqlModule.select(buildSelect(runtimeContext)); } @Comment("执行`selectOne`查询") public Map selectOne(RuntimeContext runtimeContext) { preHandle(SqlMode.SELECT_ONE); - Map result = sqlModule.selectOne(buildSelect(runtimeContext)); - mapperResults(runtimeContext, Arrays.asList(result)); - return result; + return sqlModule.selectOne(buildSelect(runtimeContext)); } @Comment("执行分页查询") public Object page(RuntimeContext runtimeContext) { preHandle(SqlMode.PAGE); PageResultBuilder> pageResultBuilder = sqlModule.executePage(buildSelect(runtimeContext)); - mapperResults(runtimeContext, pageResultBuilder.getList()); return sqlModule.buildPageResult(pageResultBuilder); } @@ -477,7 +386,6 @@ public class NamedTable extends TableBase implements JoinInterface { @Comment(name = "offset", value = "跳过条数") long offset) { preHandle(SqlMode.PAGE); PageResultBuilder> pageResultBuilder = sqlModule.executePage(buildSelect(runtimeContext), new Page(limit, offset)); - mapperResults(runtimeContext, pageResultBuilder.getList()); return sqlModule.buildPageResult(pageResultBuilder); } -- Gitee