/**
* Copyright (c) 2011-2014, hubin (jobob@qq.com).
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.baomidou.mybatisplus.mapper;
import com.baomidou.mybatisplus.entity.TableFieldInfo;
import com.baomidou.mybatisplus.entity.TableInfo;
import com.baomidou.mybatisplus.enums.SqlMethod;
import com.baomidou.mybatisplus.toolkit.SqlReservedWords;
import com.baomidou.mybatisplus.toolkit.StringUtils;
import org.apache.ibatis.mapping.SqlSource;
import org.apache.ibatis.scripting.defaults.RawSqlSource;
import java.util.List;
import java.util.Map;
/**
* <p>
* SQL 自动注入逻辑处理器<br>
* 1、支持逻辑删除
* </p>
*
* @author hubin willenfoo
* @Date 2017-09-09
*/
public class LogicSqlInjector extends AutoSqlInjector {
/**
* 根据 ID 删除
*/
@Override
protected void injectDeleteByIdSql(boolean batch, Class<?> mapperClass, Class<?> modelClass, TableInfo table) {
if (table.isLogicDelete()) {
// 逻辑删除注入
SqlMethod sqlMethod = SqlMethod.LOGIC_DELETE_BY_ID;
SqlSource sqlSource;
String idStr = table.getKeyColumn();
if (batch) {
sqlMethod = SqlMethod.LOGIC_DELETE_BATCH_BY_IDS;
StringBuilder ids = new StringBuilder();
ids.append("\n<foreach item=\"item\" index=\"index\" collection=\"list\" separator=\",\">");
ids.append("#{item}");
ids.append("\n</foreach>");
idStr = ids.toString();
}
String sql = String.format(sqlMethod.getSql(), table.getTableName(), sqlLogicSet(table),
table.getKeyColumn(), idStr);
sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass);
this.addUpdateMappedStatement(mapperClass, modelClass, sqlMethod.getMethod(), sqlSource);
} else {
// 正常删除
super.injectDeleteByIdSql(batch, mapperClass, modelClass, table);
}
}
/**
* 根据 SQL 删除
*/
@Override
protected void injectDeleteSql(Class<?> mapperClass, Class<?> modelClass, TableInfo table) {
if (table.isLogicDelete()) {
// 逻辑删除注入
SqlMethod sqlMethod = SqlMethod.LOGIC_DELETE;
String sql = String.format(sqlMethod.getSql(), table.getTableName(), sqlLogicSet(table),
sqlWhereEntityWrapper(table));
SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass);
this.addUpdateMappedStatement(mapperClass, modelClass, sqlMethod.getMethod(), sqlSource);
} else {
// 正常删除
super.injectDeleteSql(mapperClass, modelClass, table);
}
}
/**
* 根据 MAP 删除
*/
@Override
protected void injectDeleteByMapSql(Class<?> mapperClass, TableInfo table) {
if (table.isLogicDelete()) {
// 逻辑删除注入
SqlMethod sqlMethod = SqlMethod.LOGIC_DELETE_BY_MAP;
String sql = String.format(sqlMethod.getSql(), table.getTableName(), sqlLogicSet(table),
sqlWhereByMap(table));
SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, Map.class);
this.addUpdateMappedStatement(mapperClass, Map.class, sqlMethod.getMethod(), sqlSource);
} else {
// 正常删除
super.injectDeleteByMapSql(mapperClass, table);
}
}
/**
* <p>
* 注入查询 SQL 语句
* </p>
*
* @param batch
* 是否为批量插入
* @param mapperClass
* @param modelClass
* @param table
*/
protected void injectSelectByIdSql(boolean batch, Class<?> mapperClass, Class<?> modelClass, TableInfo table) {
if (table.isLogicDelete()) {
SqlMethod sqlMethod = SqlMethod.LOGIC_SELECT_BY_ID;
SqlSource sqlSource;
if (batch) {
sqlMethod = SqlMethod.LOGIC_SELECT_BATCH_BY_IDS;
StringBuilder ids = new StringBuilder();
ids.append("\n<foreach item=\"item\" index=\"index\" collection=\"list\" separator=\",\">");
ids.append("#{item}");
ids.append("\n</foreach>");
sqlSource = languageDriver.createSqlSource(configuration, String.format(sqlMethod.getSql(), sqlSelectColumns(table, false),
table.getTableName(), table.getKeyColumn(), ids.toString(), getLogicDeleteSql(table)), modelClass);
} else {
sqlSource = new RawSqlSource(configuration, String.format(sqlMethod.getSql(), sqlSelectColumns(table, false), table.getTableName(),
table.getKeyColumn(), table.getKeyProperty(), getLogicDeleteSql(table)), Object.class);
}
this.addSelectMappedStatement(mapperClass, sqlMethod.getMethod(), sqlSource, modelClass, table);
} else {
// 正常查询
super.injectSelectByIdSql(batch, mapperClass, modelClass, table);
}
}
/**
* <p>
* 注入更新 SQL 语句
* </p>
*
* @param mapperClass
* @param modelClass
* @param table
*/
protected void injectUpdateByIdSql(boolean selective, Class<?> mapperClass, Class<?> modelClass, TableInfo table) {
if (table.isLogicDelete()) {
SqlMethod sqlMethod = selective ? SqlMethod.LOGIC_UPDATE_BY_ID : SqlMethod.LOGIC_UPDATE_ALL_COLUMN_BY_ID;
String sql = String.format(sqlMethod.getSql(), table.getTableName(), sqlSet(selective, table, null),
table.getKeyColumn(), table.getKeyProperty(), getLogicDeleteSql(table));
SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass);
this.addUpdateMappedStatement(mapperClass, modelClass, sqlMethod.getMethod(), sqlSource);
} else {
super.injectUpdateByIdSql(selective, mapperClass, modelClass, table);
}
}
/**
* <p>
* SQL 更新 set 语句
* </p>
*
* @param table
* 表信息
* @return sql and 片段
*/
public String getLogicDeleteSql(TableInfo table) {
StringBuilder sql = new StringBuilder();
List<TableFieldInfo> fieldList = table.getFieldList();
for (TableFieldInfo fieldInfo : fieldList) {
if (fieldInfo.isLogicDelete()) {
sql.append(" AND ").append(fieldInfo.getColumn());
if ("java.lang.String".equals(fieldInfo.getPropertyType())) {
sql.append("='").append(fieldInfo.getLogicNotDeleteValue()).append("'");
} else {
sql.append("=").append(fieldInfo.getLogicNotDeleteValue());
}
}
}
return sql.toString();
}
/**
* <p>
* SQL 更新 set 语句
* </p>
*
* @param table
* 表信息
* @return sql set 片段
*/
protected String sqlLogicSet(TableInfo table) {
List<TableFieldInfo> fieldList = table.getFieldList();
StringBuilder set = new StringBuilder("SET ");
int i = 0;
for (TableFieldInfo fieldInfo : fieldList) {
if (fieldInfo.isLogicDelete()) {
if (++i > 1) {
set.append(",");
}
set.append(fieldInfo.getColumn()).append("=");
if ("java.lang.String".equals(fieldInfo.getPropertyType())) {
set.append("'").append(fieldInfo.getLogicDeleteValue()).append("'");
} else {
set.append(fieldInfo.getLogicDeleteValue());
}
}
}
return set.toString();
}
// ------------ 处理逻辑删除条件过滤 ------------
@Override
protected String sqlWhere(TableInfo table) {
if (table.isLogicDelete()) {
StringBuilder where = new StringBuilder("\n<where>");
// 过滤逻辑
List<TableFieldInfo> fieldList = table.getFieldList();
// EW 逻辑
if (StringUtils.isNotEmpty(table.getKeyProperty())) {
where.append("\n<if test=\"ew.").append(table.getKeyProperty()).append("!=null\">");
where.append(" AND ").append(table.getKeyColumn()).append("=#{ew.");
where.append(table.getKeyProperty()).append("}");
where.append("</if>");
}
for (TableFieldInfo fieldInfo : fieldList) {
where.append(convertIfTag(fieldInfo, "ew.", false));
where.append(" AND ").append(fieldInfo.getColumn()).append("=#{ew.");
where.append(fieldInfo.getEl()).append("}");
where.append(convertIfTag(fieldInfo, true));
}
// 过滤逻辑
where.append("\n").append(getLogicDeleteSql(table));
where.append("\n</where>");
return where.toString();
}
// 正常逻辑
return super.sqlWhere(table);
}
@Override
protected String sqlWhereEntityWrapper(TableInfo table) {
if (table.isLogicDelete()) {
StringBuilder where = new StringBuilder("\n<where>");
// EW 逻辑
where.append("\n<if test=\"ew!=null\">\n<if test=\"ew.entity!=null\">");
if (StringUtils.isNotEmpty(table.getKeyProperty())) {
where.append("\n<if test=\"ew.entity.").append(table.getKeyProperty()).append("!=null\">");
where.append(" AND ").append(table.getKeyColumn()).append("=#{ew.entity.");
where.append(table.getKeyProperty()).append("}");
where.append("</if>");
}
List<TableFieldInfo> fieldList = table.getFieldList();
for (TableFieldInfo fieldInfo : fieldList) {
where.append(convertIfTag(fieldInfo, "ew.entity.", false));
where.append(" AND ").append(fieldInfo.getColumn()).append("=#{ew.entity.");
where.append(fieldInfo.getEl()).append("}");
where.append(convertIfTag(fieldInfo, true));
}
where.append("\n</if>");
where.append("\n</if>");
// 过滤逻辑, 这段代码放在这里的原因,第一:不把 逻辑的过滤 放在where条件 第一位, 能够方便利用索引
where.append("\n").append(getLogicDeleteSql(table));
where.append("\n<if test=\"ew!=null\">\n<if test=\"ew.sqlSegment!=null\">${ew.sqlSegment}</if>\n</if>");
where.append("\n</where>");
return where.toString();
}
// 正常逻辑
return super.sqlWhereEntityWrapper(table);
}
@Override
protected String sqlWhereByMap(TableInfo table) {
if (table.isLogicDelete()) {
StringBuilder where = new StringBuilder();
where.append("\n<where>");
// MAP 逻辑
where.append("\n<if test=\"cm!=null and !cm.isEmpty\">");
where.append("\n<foreach collection=\"cm.keys\" item=\"k\" separator=\"AND\">");
where.append("\n<if test=\"cm[k] != null\">");
where.append(SqlReservedWords.convert(getGlobalConfig(), "\n${k}")).append(" = #{cm[${k}]}");
where.append("</if>");
where.append("\n</foreach>");
where.append("\n</if>");
// 过滤逻辑
where.append("\n").append(getLogicDeleteSql(table));
where.append("\n</where>");
return where.toString();
}
// 正常逻辑
return super.sqlWhereByMap(table);
}
}