一.持久层接口补充
1.Mapper 层选装件
选装件是 Mybatis-Plus 提供的一些扩展方法,它们位于 com.baomidou.mybatisplus.extension.injector.methods 包下。这些方法需要配合Sql 注入器使用,以扩展 Mapper 接口的功能。
使用这些选装件前,需要确保已经正确配置了 Sql 注入器。
选装件说明
1>alwaysUpdateSomeColumnById
1
| int alwaysUpdateSomeColumnById(T entity);
|
源码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82
| package com.baomidou.mybatisplus.extension.injector.methods;
import com.baomidou.mybatisplus.core.enums.SqlMethod; import com.baomidou.mybatisplus.core.injector.AbstractMethod; import com.baomidou.mybatisplus.core.metadata.TableFieldInfo; import com.baomidou.mybatisplus.core.metadata.TableInfo; import com.baomidou.mybatisplus.core.toolkit.sql.SqlScriptUtils; import lombok.Setter; import lombok.experimental.Accessors; import org.apache.ibatis.mapping.MappedStatement; import org.apache.ibatis.mapping.SqlSource;
import java.util.function.Predicate;
public class AlwaysUpdateSomeColumnById extends AbstractMethod {
@Setter @Accessors(chain = true) private Predicate<TableFieldInfo> predicate;
public AlwaysUpdateSomeColumnById(String name, Predicate<TableFieldInfo> predicate) { super(name); this.predicate = predicate; }
public AlwaysUpdateSomeColumnById() { super("alwaysUpdateSomeColumnById"); }
public AlwaysUpdateSomeColumnById(Predicate<TableFieldInfo> predicate) { super("alwaysUpdateSomeColumnById"); this.predicate = predicate; }
@Override public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) { SqlMethod sqlMethod = SqlMethod.UPDATE_BY_ID; final String additional = optlockVersion(tableInfo) + tableInfo.getLogicDeleteSql(true, true); String sqlSet = this.filterTableFieldInfo(tableInfo.getFieldList(), getPredicate(), i -> i.getSqlSet(true, ENTITY_DOT), NEWLINE); sqlSet = SqlScriptUtils.convertSet(sqlSet); String sql = String.format(sqlMethod.getSql(), tableInfo.getTableName(), sqlSet, tableInfo.getKeyColumn(), ENTITY_DOT + tableInfo.getKeyProperty(), additional); SqlSource sqlSource = super.createSqlSource(configuration, sql, modelClass); return addUpdateMappedStatement(mapperClass, modelClass, methodName, sqlSource); }
private Predicate<TableFieldInfo> getPredicate() { Predicate<TableFieldInfo> noLogic = t -> !t.isLogicDelete(); if (predicate != null) { return noLogic.and(predicate); } return noLogic; }
}
|
功能:
这个方法用于在更新操作时,无论实体对象的某些字段是否有变化,都会强制更新这些字段。这在某些业务场景下非常有用,比如更新时间戳字段,确保每次更新操作都会更新该字段。
使用场景:
当你需要在每次更新记录时,都更新某些特定的字段(如更新时间、版本号等),即使这些字段在实体对象中没有变化。
2>insertBatchSomeColumn
1
| int insertBatchSomeColumn(List<T> entityList);
|
源码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119
| package com.baomidou.mybatisplus.extension.injector.methods;
import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.core.enums.SqlMethod; import com.baomidou.mybatisplus.core.injector.AbstractMethod; import com.baomidou.mybatisplus.core.metadata.TableFieldInfo; import com.baomidou.mybatisplus.core.metadata.TableInfo; import com.baomidou.mybatisplus.core.metadata.TableInfoHelper; import com.baomidou.mybatisplus.core.toolkit.sql.SqlInjectionUtils; import com.baomidou.mybatisplus.core.toolkit.sql.SqlScriptUtils; import lombok.Setter; import lombok.experimental.Accessors; import org.apache.ibatis.executor.keygen.Jdbc3KeyGenerator; import org.apache.ibatis.executor.keygen.KeyGenerator; import org.apache.ibatis.executor.keygen.NoKeyGenerator; import org.apache.ibatis.mapping.MappedStatement; import org.apache.ibatis.mapping.SqlSource;
import java.util.List; import java.util.function.Predicate;
public class InsertBatchSomeColumn extends AbstractMethod {
@Setter @Accessors(chain = true) private Predicate<TableFieldInfo> predicate;
public InsertBatchSomeColumn() { super("insertBatchSomeColumn"); }
public InsertBatchSomeColumn(Predicate<TableFieldInfo> predicate) { super("insertBatchSomeColumn"); this.predicate = predicate; }
public InsertBatchSomeColumn(String name, Predicate<TableFieldInfo> predicate) { super(name); this.predicate = predicate; }
@SuppressWarnings("Duplicates") @Override public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) { KeyGenerator keyGenerator = NoKeyGenerator.INSTANCE; SqlMethod sqlMethod = SqlMethod.INSERT_ONE; List<TableFieldInfo> fieldList = tableInfo.getFieldList(); String insertSqlColumn = tableInfo.getKeyInsertSqlColumn(true, null, false) + this.filterTableFieldInfo(fieldList, predicate, TableFieldInfo::getInsertSqlColumn, EMPTY); String columnScript = LEFT_BRACKET + insertSqlColumn.substring(0, insertSqlColumn.length() - 1) + RIGHT_BRACKET; String insertSqlProperty = tableInfo.getKeyInsertSqlProperty(true, ENTITY_DOT, false) + this.filterTableFieldInfo(fieldList, predicate, i -> i.getInsertSqlProperty(ENTITY_DOT), EMPTY); insertSqlProperty = LEFT_BRACKET + insertSqlProperty.substring(0, insertSqlProperty.length() - 1) + RIGHT_BRACKET; String valuesScript = SqlScriptUtils.convertForeach(insertSqlProperty, "list", null, ENTITY, COMMA); String keyProperty = null; String keyColumn = null; if (tableInfo.havePK()) { if (tableInfo.getIdType() == IdType.AUTO) { keyGenerator = Jdbc3KeyGenerator.INSTANCE; keyProperty = tableInfo.getKeyProperty(); keyColumn = SqlInjectionUtils.removeEscapeCharacter(tableInfo.getKeyColumn()); } else { if (null != tableInfo.getKeySequence()) { keyGenerator = TableInfoHelper.genKeyGenerator(this.methodName, tableInfo, builderAssistant); keyProperty = tableInfo.getKeyProperty(); keyColumn = tableInfo.getKeyColumn(); } } } String sql = String.format(sqlMethod.getSql(), tableInfo.getTableName(), columnScript, valuesScript); SqlSource sqlSource = super.createSqlSource(configuration, sql, modelClass); return this.addInsertMappedStatement(mapperClass, modelClass, methodName, sqlSource, keyGenerator, keyProperty, keyColumn); }
}
|
功能:
这个方法用于批量插入实体对象,但只插入实体对象中指定的某些字段。这在需要批量插入数据,但又不希望插入所有字段时非常有用。
使用场景:
当你需要批量插入数据,并且希望只插入实体对象中的部分字段,以提高插入效率或保护敏感数据。
3>logicDeleteByIdWithFill
1
| int logicDeleteByIdWithFill(T entity);
|
源码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73
| package com.baomidou.mybatisplus.extension.injector.methods;
import com.baomidou.mybatisplus.core.enums.SqlMethod; import com.baomidou.mybatisplus.core.injector.AbstractMethod; import com.baomidou.mybatisplus.core.metadata.TableFieldInfo; import com.baomidou.mybatisplus.core.metadata.TableInfo; import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; import org.apache.ibatis.mapping.MappedStatement; import org.apache.ibatis.mapping.SqlSource;
import java.util.List;
import static java.util.stream.Collectors.joining; import static java.util.stream.Collectors.toList;
@Deprecated public class LogicDeleteByIdWithFill extends AbstractMethod {
public LogicDeleteByIdWithFill() { super("deleteByIdWithFill"); }
public LogicDeleteByIdWithFill(String name) { super(name); }
@Override public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) { String sql; SqlMethod sqlMethod = SqlMethod.LOGIC_DELETE_BY_ID; if (tableInfo.isWithLogicDelete()) { List<TableFieldInfo> fieldInfos = tableInfo.getFieldList().stream() .filter(TableFieldInfo::isWithUpdateFill) .filter(f -> !f.isLogicDelete()) .collect(toList()); if (CollectionUtils.isNotEmpty(fieldInfos)) { String sqlSet = "SET " + fieldInfos.stream().map(i -> i.getSqlSet(EMPTY)).collect(joining(EMPTY)) + tableInfo.getLogicDeleteSql(false, false); sql = String.format(sqlMethod.getSql(), tableInfo.getTableName(), sqlSet, tableInfo.getKeyColumn(), tableInfo.getKeyProperty(), tableInfo.getLogicDeleteSql(true, true)); } else { sql = String.format(sqlMethod.getSql(), tableInfo.getTableName(), sqlLogicSet(tableInfo), tableInfo.getKeyColumn(), tableInfo.getKeyProperty(), tableInfo.getLogicDeleteSql(true, true)); } } else { sqlMethod = SqlMethod.DELETE_BY_ID; sql = String.format(sqlMethod.getSql(), tableInfo.getTableName(), tableInfo.getKeyColumn(), tableInfo.getKeyProperty()); } SqlSource sqlSource = super.createSqlSource(configuration, sql, modelClass); return addUpdateMappedStatement(mapperClass, modelClass, methodName, sqlSource); }
}
|
功能:
这个方法用于逻辑删除记录,并填充实体对象中的某些字段。逻辑删除意味着不是真正从数据库中删除记录,而是通过更新某个字段(如 deleted 字段)来标记记录已被删除。
使用场景:
当你需要实现逻辑删除功能,并且希望在删除操作时自动填充实体对象中的某些字段(如删除时间、删除人等)。
使用提示
- 在使用这些选装件之前,确保你的项目中已经正确配置了 Sql 注入器。
- 这些方法通常需要在 Mapper 接口中显式声明,以便 Mybatis-Plus 能够识别并生成相应的 SQL 语句。
- 每个选装件都有其特定的使用场景,根据业务需求选择合适的方法。
- 在实际使用中,可能需要结合实体对象的注解(如 @TableField、@TableLogic 等)来实现更复杂的功能。