逻辑删除根据官方配置就行,重点是配置后的支持物理删除


import cn.dev33.satoken.stp.StpUtil;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.override.MybatisMapperProxy;
import com.baomidou.mybatisplus.core.toolkit.MybatisUtils;
import com.baomidou.mybatisplus.extension.toolkit.SqlHelper;
import org.apache.ibatis.session.SqlSession;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.time.LocalDateTime;
import java.util.Optional;

/**
 * 自定义BaseMapper
 * 这里不会打印日志,可以在 service 中进行处理
 */
public interface MyBaseMapper<Entity> extends BaseMapper<Entity> {

    /**
     * 根据ID逻辑删除
     *
     * @param id 主键ID
     * @return 是否删除成功
     */
    default boolean deleteLogicById(Integer id) {
        // 使用 UpdateWrapper 构建更新条件
        UpdateWrapper<Entity> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("id", id)
                .set("is_deleted", 1)
                .set("deleted_by", Optional.of(StpUtil.getLoginIdAsInt()).orElse(0))
                .set("deleted_at", LocalDateTime.now());

        // 直接更新
        return SqlHelper.retBool(this.update(updateWrapper));
    }

    /**
     * 根据ID物理删除
     *
     * @param id 主键ID
     * @return 是否删除成功
     */
    default boolean deletePhysicalById(Integer id) {
        try {
            // 获取当前SqlSession和Mapper信息
            MybatisMapperProxy<?> mybatisMapperProxy = MybatisUtils.getMybatisMapperProxy(this);
            SqlSession sqlSession = mybatisMapperProxy.getSqlSession();

            // 获取实体类型和表名
            String tableName = getTableName();

            // 构建物理删除SQL
            String sql = "DELETE FROM " + tableName + " WHERE id = ?";

            // 直接获取JDBC连接,完全绕过MyBatis拦截器
            java.sql.Connection connection = sqlSession.getConnection();

            try (java.sql.PreparedStatement ps = connection.prepareStatement(sql)) {
                ps.setInt(1, id);
                int rows = ps.executeUpdate();
                return rows > 0;
            }
        } catch (Exception e) {
            throw new RuntimeException("物理删除失败", e);
        }
    }

    /**
     * 获取当前Mapper对应实体的表名
     *
     * @return 表名
     */
    @SuppressWarnings("unchecked")
    default String getTableName() {
        try {
            // 获取当前Mapper接口
            MybatisMapperProxy<?> mybatisMapperProxy = MybatisUtils.getMybatisMapperProxy(this);
            Class<?> mapperInterface = mybatisMapperProxy.getMapperInterface();

            // 查找泛型类型参数T
            Type[] genericInterfaces = mapperInterface.getGenericInterfaces();
            for (Type genericInterface : genericInterfaces) {
                if (genericInterface instanceof ParameterizedType) {
                    ParameterizedType parameterizedType = (ParameterizedType) genericInterface;
                    if (parameterizedType.getRawType() == MyBaseMapper.class
                            || parameterizedType.getRawType() == BaseMapper.class) {
                        Type[] typeArguments = parameterizedType.getActualTypeArguments();
                        if (typeArguments.length > 0 && typeArguments[0] instanceof Class) {
                            Class<?> entityClass = (Class<?>) typeArguments[0];

                            // 只从@TableName注解获取表名
                            if (entityClass.isAnnotationPresent(TableName.class)) {
                                return entityClass.getAnnotation(TableName.class).value();
                            }

                            // 如果没有注解,报错
                            throw new RuntimeException(
                                    "实体类 " + entityClass.getName() + " 没有 @TableName 注解,无法获取表名");
                        }
                    }
                }
            }

            throw new RuntimeException("无法确定实体类对应的表名,请在实体类上添加 @TableName 注解");
        } catch (Exception e) {
            throw new RuntimeException("获取表名失败: " + e.getMessage(), e);
        }
    }

    /**
     * 获取泛型类型T
     *
     * @return 实体类类型
     */
    @SuppressWarnings("unchecked")
    default Class<Entity> getEntityClass() {
        Type genericInterface = this.getClass().getGenericInterfaces()[0];
        if (genericInterface instanceof ParameterizedType) {
            Type[] typeArguments = ((ParameterizedType) genericInterface).getActualTypeArguments();
            return (Class<Entity>) typeArguments[0];
        }

        // 尝试从接口定义获取
        Type mapperInterfaceType = getClass().getInterfaces()[0].getGenericInterfaces()[0];
        if (mapperInterfaceType instanceof ParameterizedType) {
            Type[] typeArguments = ((ParameterizedType) mapperInterfaceType).getActualTypeArguments();
            return (Class<Entity>) typeArguments[0];
        }

        throw new RuntimeException("无法获取实体类型");
    }
}