From 0afe2e54017d59fb886bb3af03018c1e6957ab92 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=80=E6=BA=90=E6=B5=B7=E5=93=A5?= Date: Thu, 2 Mar 2023 16:32:13 +0800 Subject: [PATCH] add logic delete support --- .../java/com/mybatisflex/core/BaseMapper.java | 12 +- .../core/dialect/CommonsDialectImpl.java | 139 ++++++++++++++++-- .../mybatisflex/core/dialect/IDialect.java | 4 +- .../core/provider/EntitySqlProvider.java | 34 ++++- 4 files changed, 168 insertions(+), 21 deletions(-) diff --git a/mybatis-flex-core/src/main/java/com/mybatisflex/core/BaseMapper.java b/mybatis-flex-core/src/main/java/com/mybatisflex/core/BaseMapper.java index 87b0c275..d1eb97ed 100644 --- a/mybatis-flex-core/src/main/java/com/mybatisflex/core/BaseMapper.java +++ b/mybatis-flex-core/src/main/java/com/mybatisflex/core/BaseMapper.java @@ -15,6 +15,7 @@ */ package com.mybatisflex.core; +import com.mybatisflex.core.exception.FlexExceptions; import com.mybatisflex.core.paginate.Page; import com.mybatisflex.core.provider.EntitySqlProvider; import com.mybatisflex.core.querywrapper.QueryColumn; @@ -82,6 +83,9 @@ public interface BaseMapper { * @return 返回影响的行数 */ default int deleteByMap(Map whereConditions) { + if (whereConditions == null || whereConditions.isEmpty()) { + throw FlexExceptions.wrap("deleteByMap is not allow empty map."); + } return deleteByQuery(QueryWrapper.create().where(whereConditions)); } @@ -109,7 +113,7 @@ public interface BaseMapper { /** * 根据主键来更新数据到数据库 * - * @param entity 数据内容 + * @param entity 数据内容 * @param ignoreNulls 是否忽略空内容字段 * @return 返回影响的行数 * @see com.mybatisflex.core.provider.EntitySqlProvider#update(Map, ProviderContext) @@ -145,9 +149,9 @@ public interface BaseMapper { /** * 根据 query 构建的条件来更新数据 * - * @param entity 数据内容 - * @param ignoreNulls 是否忽略空值 - * @param queryWrapper query 条件 + * @param entity 数据内容 + * @param ignoreNulls 是否忽略空值 + * @param queryWrapper query 条件 * @return * @see com.mybatisflex.core.provider.EntitySqlProvider#updateByQuery(Map, ProviderContext) */ diff --git a/mybatis-flex-core/src/main/java/com/mybatisflex/core/dialect/CommonsDialectImpl.java b/mybatis-flex-core/src/main/java/com/mybatisflex/core/dialect/CommonsDialectImpl.java index 1b8e2c23..daa3343d 100644 --- a/mybatis-flex-core/src/main/java/com/mybatisflex/core/dialect/CommonsDialectImpl.java +++ b/mybatis-flex-core/src/main/java/com/mybatisflex/core/dialect/CommonsDialectImpl.java @@ -402,12 +402,109 @@ public class CommonsDialectImpl implements IDialect { @Override public String forDeleteEntityById(TableInfo tableInfo) { - return forDeleteById(tableInfo.getTableName(), tableInfo.getPrimaryKeys()); + String logicDeleteColumn = tableInfo.getLogicDeleteColumn(); + + //正常删除 + if (StringUtil.isBlank(logicDeleteColumn)) { + return forDeleteById(tableInfo.getTableName(), tableInfo.getPrimaryKeys()); + } + + //逻辑删除 + StringBuilder sql = new StringBuilder(); + String[] primaryKeys = tableInfo.getPrimaryKeys(); + + sql.append("UPDATE ").append(wrap(tableInfo.getTableName())).append(" SET "); + sql.append(wrap(logicDeleteColumn)).append(" = 1"); + sql.append(" WHERE "); + for (int i = 0; i < primaryKeys.length; i++) { + if (i > 0) { + sql.append(" AND "); + } + sql.append(wrap(primaryKeys[i])).append(" = ?"); + } + + sql.append(" AND ").append(wrap(logicDeleteColumn)).append(" = 0 "); + + return sql.toString(); } @Override - public String forDeleteEntityBatchById(TableInfo tableInfo, Object[] primaryValues) { - return forDeleteBatchByIds(tableInfo.getTableName(), tableInfo.getPrimaryKeys(), primaryValues); + public String forDeleteEntityBatchByIds(TableInfo tableInfo, Object[] primaryValues) { + String logicDeleteColumn = tableInfo.getLogicDeleteColumn(); + + //正常删除 + if (StringUtil.isBlank(logicDeleteColumn)) { + return forDeleteBatchByIds(tableInfo.getTableName(), tableInfo.getPrimaryKeys(), primaryValues); + } + + StringBuilder sql = new StringBuilder(); + sql.append("UPDATE"); + sql.append(wrap(tableInfo.getTableName())); + sql.append("SET ").append(wrap(logicDeleteColumn)).append(" = 1"); + sql.append(" WHERE "); + + String[] primaryKeys = tableInfo.getPrimaryKeys(); + + //多主键的场景 + if (primaryKeys.length > 1) { + for (int i = 0; i < primaryValues.length / primaryKeys.length; i++) { + if (i > 0) { + sql.append(" OR "); + } + sql.append("("); + for (int j = 0; j < primaryKeys.length; j++) { + if (j > 0) { + sql.append(" AND "); + } + sql.append(wrap(primaryKeys[j])).append(" = ?"); + } + sql.append(")"); + } + } + // 单主键 + else { + for (int i = 0; i < primaryValues.length; i++) { + if (i > 0) { + sql.append(" OR "); + } + sql.append(wrap(primaryKeys[0])).append(" = ?"); + } + } + return sql.toString(); + } + + @Override + public String forDeleteEntityBatchByQuery(TableInfo tableInfo, QueryWrapper queryWrapper) { + + String logicDeleteColumn = tableInfo.getLogicDeleteColumn(); + + //正常删除 + if (StringUtil.isBlank(logicDeleteColumn)) { + return forDeleteByQuery(queryWrapper); + } + + + //逻辑删除 + List queryTables = CPI.getQueryTables(queryWrapper); + List joinTables = CPI.getJoinTables(queryWrapper); + List allTables = CollectionUtil.merge(queryTables, joinTables); + + //ignore selectColumns + StringBuilder sqlBuilder = new StringBuilder("UPDATE "); + sqlBuilder.append(wrap(tableInfo.getTableName())); + sqlBuilder.append(" SET ").append(wrap(logicDeleteColumn)).append(" = 1 "); + + + buildJoinSql(sqlBuilder, queryWrapper, allTables); + buildWhereSql(sqlBuilder, queryWrapper, allTables); + buildGroupBySql(sqlBuilder, queryWrapper, allTables); + buildHavingSql(sqlBuilder, queryWrapper, allTables); + + //ignore orderBy and limit + //buildOrderBySql(sqlBuilder, queryWrapper); + //buildLimitSql(sqlBuilder, queryWrapper); + + return sqlBuilder.toString(); } @@ -419,22 +516,20 @@ public class CommonsDialectImpl implements IDialect { String[] primaryKeys = tableInfo.getPrimaryKeys(); sql.append("UPDATE ").append(wrap(tableInfo.getTableName())).append(" SET "); - int index = 0; + + StringJoiner stringJoiner = new StringJoiner(", "); + for (String modifyAttr : modifyAttrs) { - if (index > 0) { - sql.append(", "); - } - sql.append(wrap(modifyAttr)).append(" = ? "); - index++; + stringJoiner.add(wrap(modifyAttr) + " = ?"); } Map onUpdateColumns = tableInfo.getOnUpdateColumns(); if (onUpdateColumns != null && !onUpdateColumns.isEmpty()) { - StringJoiner stringJoiner = new StringJoiner(", "); onUpdateColumns.forEach((column, value) -> stringJoiner.add(wrap(column) + " = " + value)); - sql.append(", ").append(stringJoiner); } + sql.append(stringJoiner); + sql.append(" WHERE "); for (int i = 0; i < primaryKeys.length; i++) { if (i > 0) { @@ -443,6 +538,11 @@ public class CommonsDialectImpl implements IDialect { sql.append(wrap(primaryKeys[i])).append(" = ?"); } + String logicDeleteColumn = tableInfo.getLogicDeleteColumn(); + if (StringUtil.isNotBlank(logicDeleteColumn)) { + sql.append(" AND ").append(wrap(logicDeleteColumn)).append(" = 0 "); + } + return sql.toString(); } @@ -487,6 +587,13 @@ public class CommonsDialectImpl implements IDialect { } sql.append(wrap(pKeys[i])).append(" = ?"); } + + //逻辑删除的情况下,需要添加逻辑删除的条件 + String logicDeleteColumn = tableInfo.getLogicDeleteColumn(); + if (StringUtil.isNotBlank(logicDeleteColumn)) { + sql.append(" AND ").append(wrap(logicDeleteColumn)).append(" = 0 "); + } + return sql.toString(); } @@ -498,6 +605,11 @@ public class CommonsDialectImpl implements IDialect { sql.append(" WHERE "); String[] primaryKeys = tableInfo.getPrimaryKeys(); + String logicDeleteColumn = tableInfo.getLogicDeleteColumn(); + if (StringUtil.isNotBlank(logicDeleteColumn)) { + sql.append(wrap(logicDeleteColumn)).append(" = 0 AND ("); + } + //多主键的场景 if (primaryKeys.length > 1) { for (int i = 0; i < primaryValues.length / primaryKeys.length; i++) { @@ -523,6 +635,11 @@ public class CommonsDialectImpl implements IDialect { sql.append(wrap(primaryKeys[0])).append(" = ?"); } } + + if (StringUtil.isNotBlank(logicDeleteColumn)) { + sql.append(wrap(logicDeleteColumn)).append(" )"); + } + return sql.toString(); } diff --git a/mybatis-flex-core/src/main/java/com/mybatisflex/core/dialect/IDialect.java b/mybatis-flex-core/src/main/java/com/mybatisflex/core/dialect/IDialect.java index e5e919ca..480e564d 100644 --- a/mybatis-flex-core/src/main/java/com/mybatisflex/core/dialect/IDialect.java +++ b/mybatis-flex-core/src/main/java/com/mybatisflex/core/dialect/IDialect.java @@ -65,7 +65,9 @@ public interface IDialect { String forDeleteEntityById(TableInfo tableInfo); - String forDeleteEntityBatchById(TableInfo tableInfo, Object[] primaryValues); + String forDeleteEntityBatchByIds(TableInfo tableInfo, Object[] primaryValues); + + String forDeleteEntityBatchByQuery(TableInfo tableInfo, QueryWrapper queryWrapper); String forUpdateEntity(TableInfo tableInfo, Object entity, boolean ignoreNulls); diff --git a/mybatis-flex-core/src/main/java/com/mybatisflex/core/provider/EntitySqlProvider.java b/mybatis-flex-core/src/main/java/com/mybatisflex/core/provider/EntitySqlProvider.java index d2c4e844..1afb850c 100644 --- a/mybatis-flex-core/src/main/java/com/mybatisflex/core/provider/EntitySqlProvider.java +++ b/mybatis-flex-core/src/main/java/com/mybatisflex/core/provider/EntitySqlProvider.java @@ -17,11 +17,14 @@ package com.mybatisflex.core.provider; import com.mybatisflex.core.dialect.DialectFactory; import com.mybatisflex.core.exception.FlexExceptions; +import com.mybatisflex.core.querywrapper.QueryColumn; +import com.mybatisflex.core.querywrapper.QueryCondition; import com.mybatisflex.core.querywrapper.QueryWrapper; import com.mybatisflex.core.querywrapper.CPI; import com.mybatisflex.core.table.TableInfo; import com.mybatisflex.core.util.ArrayUtil; import com.mybatisflex.core.util.CollectionUtil; +import com.mybatisflex.core.util.StringUtil; import org.apache.ibatis.builder.annotation.ProviderContext; import java.io.Serializable; @@ -127,7 +130,7 @@ public class EntitySqlProvider { TableInfo tableInfo = ProviderUtil.getTableInfo(context); ProviderUtil.setSqlArgs(params, primaryValues); - return DialectFactory.getDialect().forDeleteEntityBatchById(tableInfo, primaryValues); + return DialectFactory.getDialect().forDeleteEntityBatchByIds(tableInfo, primaryValues); } @@ -149,7 +152,8 @@ public class EntitySqlProvider { TableInfo tableInfo = ProviderUtil.getTableInfo(context); queryWrapper.from(tableInfo.getTableName()); - return DialectFactory.getDialect().forDeleteByQuery(queryWrapper); + + return DialectFactory.getDialect().forDeleteEntityBatchByQuery(tableInfo, queryWrapper); } @@ -194,8 +198,13 @@ public class EntitySqlProvider { boolean ignoreNulls = ProviderUtil.isIgnoreNulls(params); QueryWrapper queryWrapper = ProviderUtil.getQueryWrapper(params); - TableInfo tableInfo = ProviderUtil.getTableInfo(context); + + String logicDeleteColumn = tableInfo.getLogicDeleteColumn(); + if (StringUtil.isNotBlank(logicDeleteColumn)) { + queryWrapper.and(QueryCondition.create(new QueryColumn(tableInfo.getTableName(), logicDeleteColumn), 0)); + } + Object[] values = tableInfo.obtainUpdateValues(entity, ignoreNulls, true); ProviderUtil.setSqlArgs(params, ArrayUtil.concat(values, CPI.getValueArray(queryWrapper))); @@ -259,11 +268,19 @@ public class EntitySqlProvider { if (queryWrapper == null) { throw FlexExceptions.wrap("queryWrapper can not be null."); } + + TableInfo tableInfo = ProviderUtil.getTableInfo(context); + + String logicDeleteColumn = tableInfo.getLogicDeleteColumn(); + if (StringUtil.isNotBlank(logicDeleteColumn)) { + queryWrapper.and(QueryCondition.create(new QueryColumn(tableInfo.getTableName(), logicDeleteColumn), 0)); + } + Object[] values = CPI.getValueArray(queryWrapper); ProviderUtil.setSqlArgs(params, values); - TableInfo tableInfo = ProviderUtil.getTableInfo(context); queryWrapper.from(tableInfo.getTableName()); + return DialectFactory.getDialect().forSelectListByQuery(queryWrapper); } @@ -281,10 +298,17 @@ public class EntitySqlProvider { throw FlexExceptions.wrap("queryWrapper can not be null."); } + TableInfo tableInfo = ProviderUtil.getTableInfo(context); + + //逻辑删除 + String logicDeleteColumn = tableInfo.getLogicDeleteColumn(); + if (StringUtil.isNotBlank(logicDeleteColumn)) { + queryWrapper.and(QueryCondition.create(new QueryColumn(tableInfo.getTableName(), logicDeleteColumn), 0)); + } + Object[] values = CPI.getValueArray(queryWrapper); ProviderUtil.setSqlArgs(params, values); - TableInfo tableInfo = ProviderUtil.getTableInfo(context); queryWrapper.from(tableInfo.getTableName()); return DialectFactory.getDialect().forSelectCountByQuery(queryWrapper); }