前言
项目中的数据删除需要执行逻辑删除,而不是物理删除,由于项目中数据访问层使用的tkmapper组件版本比较低,暂不支持逻辑删除操作(新版本已经支持),在此基础上通过tk提供的扩展自定义逻辑删除处理功能。
自定义扩展
POM引入库
<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.20</version>
</dependency>
<!-- https://mvnrepository.com/artifact/tk.mybatis/mapper-spring-boot-starter -->
<dependency>
<groupId>tk.mybatis</groupId>
<artifactId>mapper-spring-boot-starter</artifactId>
<version>2.0.4</version>
</dependency>
新增注解LogicDelete
代码如下:
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 自定义逻辑删除注解
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.ANNOTATION_TYPE})
public @interface LogicDelete {
/**
* 正常的值:由于数据库使用的是number类型,所以我这边写默认值为0
*/
String value() default "0";
/**
* 删除的值:由于数据库使用的是number类型,所以我这边写默认值为1
*/
String devval() default "1";
}
扩展SqlHelper
代码如下:
import com.jyusun.origin.example.boot.tk.annotation.LogicDelete;
import lombok.experimental.UtilityClass;
import tk.mybatis.mapper.annotation.Version;
import tk.mybatis.mapper.entity.EntityColumn;
import tk.mybatis.mapper.mapperhelper.EntityHelper;
import tk.mybatis.mapper.mapperhelper.SqlHelper;
import tk.mybatis.mapper.version.VersionException;
import java.util.Set;
/**
* 作用描述:扩展SqlHelper
*
* @author jyusun at 2023/6/2 17:02
* @since 1.0.0
*/
@UtilityClass
public class ExtSqlHelper extends SqlHelper {
/**
* 逻辑删除sql拼接处理
*
* @param entityClass
* @return
*/
public static String logicDeleteSetColumns(Class<?> entityClass) {
StringBuilder sql = new StringBuilder();
sql.append("<set>");
//获取全部列
Set<EntityColumn> columnSet = EntityHelper.getColumns(entityClass);
//对乐观锁的支持
EntityColumn versionColumn = null;
EntityColumn logicDelete = null;
//当某个列有主键策略时,不需要考虑他的属性是否为空,因为如果为空,一定会根据主键策略给他生成一个值
for (EntityColumn column : columnSet) {
// 乐观锁注解获取
if (column.getEntityField()
.isAnnotationPresent(Version.class)) {
if (versionColumn != null) {
throw new VersionException(entityClass.getCanonicalName() + " 中包含多个带有 @Version " +
"注解的字段,一个类中只能存在一个带有" + " @Version 注解的字段!");
}
versionColumn = column;
}
// 逻辑删除注解获取
if (column.getEntityField()
.isAnnotationPresent(LogicDelete.class)) {
if (logicDelete != null) {
throw new VersionException(entityClass.getCanonicalName() + " 中包含多个带有 @LogicDelete " +
"注解的字段,一个类中只能存在一个带有 @LogicDelete 注解的字段!");
}
logicDelete = column;
}
if (!column.isId() && column.isUpdatable()) {
if (column == versionColumn) {
Version version = versionColumn.getEntityField()
.getAnnotation(Version.class);
String versionClass = version.nextVersion()
.getCanonicalName();
//version = ${@tk.mybatis.mapper.version@nextVersionClass("versionClass", version)}
sql.append(column.getColumn())
.append(" = ${@tk.mybatis.mapper.version.VersionUtil@nextVersion(")
.append("@")
.append(versionClass)
.append("@class, ")
.append(column.getProperty())
.append(")},");
}
// 组装逻辑删除的set条件 set LogicDelete 注解标记的属性 isde = 1
if (column == logicDelete) {
LogicDelete logic = logicDelete.getEntityField()
.getAnnotation(LogicDelete.class);
String delval = logic.delval();
sql.append(column.getColumn())
.append(" = ")
.append(delval)
.append(",");
}
}
}
sql.append("</set>");
return sql.toString();
}
}
扩展Provider
代码如下:
import org.apache.ibatis.mapping.MappedStatement;
import tk.mybatis.mapper.mapperhelper.MapperHelper;
import tk.mybatis.mapper.mapperhelper.MapperTemplate;
import tk.mybatis.mapper.mapperhelper.SqlHelper;
/**
* 作用描述:
* 扩展 MapperTemplate
*
* @author jyusun at 2023/6/2 16:44
* @since 1.0.0
*/
public class ExtBaseProvider extends MapperTemplate {
public ExtBaseProvider(Class<?> mapperclass, MapperHelper mapperHelper) {
super(mapperclass, mapperHelper);
}
public String customDeleteLogic(MappedStatement ms) {
Class<?> entityClass = getEntityClass(ms);
StringBuilder sql = new StringBuilder();
sql.append(SqlHelper.updateTable(entityClass,tableName(entityClass)));
sql.append(ExtSqlHelper.logicDeleteSetColumns(entityClass));
sql.append(SqlHelper.wherePKColumns(entityClass));
return sql.toString();
}
}
扩展Mapper
代码如下:
import org.apache.ibatis.annotations.UpdateProvider;
import tk.mybatis.mapper.annotation.RegisterMapper;
import tk.mybatis.mapper.common.BaseMapper;
/**
* 扩展 BaseMapper
*/
@RegisterMapper
public interface ExtBaseMapper<T> extends BaseMapper<T> {
/**
* 自定义逻辑删除
*
* @param obj 数据对象
* @return {@code Integer} 操作状态
*/
@UpdateProvider(type = ExtBaseProvider.class, method = "dynamicSQL")
int customDeleteLogic(Object obj);
}
总结
- 自定定义注解:LogicDelete
- 更新处理:ExtSqlHelper 定义一个方法 logicDeleteSetColumns 拼接字段更新处理
- 自定义提供者:ExtBaseProvider extends MapperTemplate,主要用于动态生成SQL
- 自定义映射器:ExtBaseMapper 注册 @RegisterMapper
- ExtBaseMapper 自定义方法:customDeleteLogic 指定提供者,ExtBaseMapper 与 ExtBaseProvider 方法名对应
- ExtBaseMapper.customDeleteLogic 方法标记
@UpdateProvider
注解并指定type
属性为上面定义的提供者,指定method
属性"dynamicSQL"(动态SQL)