逻辑删除(假删除)

创建一个拦截器LogicDeleteInterceptor

@Intercepts(
        @Signature(type= StatementHandler.class,method = "prepare",args = {Connection.class,Integer.class})
)
@Component
public class LogicDeleteInterceptor implements Interceptor, HandlerInterceptor {
    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        //invocation获取原始对象
        StatementHandler statementHandler = (StatementHandler) invocation.getTarget();
        //获取旧有得sql语句
        BoundSql boundSql = statementHandler.getBoundSql();
        String oldSQL = boundSql.getSql();
        String newSQL = oldSQL.replace("where 1=1","where 1=1 and is_deleted=0");
        //用newSQL替换oldSQL
        Field sql = boundSql.getClass().getDeclaredField("sql");
        sql.setAccessible(true);
        sql.set(boundSql,newSQL);
        //调用原始对象执行原始方法且返回
        return invocation.proceed();


    }
}

在WebConfig中注册拦截器

@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Autowired
    private LoginInterceptor loginInterceptor;

    @Autowired
    private LogicDeleteInterceptor logicDeleteInterceptor;
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(logicDeleteInterceptor);
        //登录接口和注册接口不拦截
        registry
                .addInterceptor(loginInterceptor)
                .excludePathPatterns("/user/login","/user/register");

    }

}

sql语句写法

逻辑删除时,controller使用@DeleteMapping,在mapper层使用<update>标签

检查用户名是否被暂用

public boolean isUsernameAvailable(String username) {
    // 检查数据库中是否存在该用户名,包括逻辑删除的用户
    User user = userRepository.findByUsername(username);
    if (user == null || user.isDeleted()) {
        // 用户不存在或已被逻辑删除,用户名可用
        return true;
    } else {
        // 用户存在且未被删除,用户名不可用
        return false;
    }
}

public User saveUser(User user) {
    if (isUsernameAvailable(user.getUsername())) {
        // 用户名可用,保存新用户
        return userRepository.save(user);
    } else {
        // 用户名不可用,抛出异常或返回错误信息
        throw new UsernameNotAvailableException("用户名已被占用");
    }
}

### 数据库中的逻辑删除及其字段设计最佳实践 #### 1. 定义逻辑删除的概念 逻辑删除是指不真正从数据库中移除数据记录,而是在表中增加一个标志位来标记该条记录是否有效。这种方式能够保留历史数据的同时避免物理删除带来的复杂性和潜在风险。 #### 2. 字段设计方案 为了支持逻辑删除功能,可以在每张需要此特性的表里加入如下几个辅助字段: - **is_deleted**: 这是最常见的做法之一,使用布尔型(Boolean)或整数(Integer),默认值设为`false`(0表示未被删除)[^1]。 ```sql ALTER TABLE table_name ADD COLUMN is_deleted BOOLEAN DEFAULT FALSE; ``` - **deleted_at**: 记录下实际发生删除操作的时间戳(Timestamp with Time Zone),有助于追踪何时进行了删除动作[^3]. ```sql ALTER TABLE table_name ADD COLUMN deleted_at TIMESTAMP WITH TIME ZONE NULL; ``` - **deleter_id**: 如果应用层面对谁执行了删除有兴趣的话,则可考虑添加这一列用来存储执行者的ID信息. ```sql ALTER TABLE table_name ADD COLUMN deleter_id INTEGER REFERENCES users(id); ``` 上述方案不仅适用于关系型数据库管理系统(RDBMSs),对于NoSQL类型的存储同样适用,比如MongoDB可以通过文档结构灵活地嵌入这些属性。 #### 3. 查询优化技巧 当实现了基于状态的软删机制之后,在编写SELECT语句时应当始终记得过滤掉那些已经被标记为已删除的状态: ```sql -- 使用is_deleted字段作为筛选条件 SELECT * FROM table_name WHERE is_deleted = false; -- 或者结合其他业务逻辑一起查询 SELECT * FROM table_name WHERE email='example@example.com' AND status=1 AND is_deleted=false ORDER BY create_time DESC; ``` 值得注意的是,如果存在大量已被标记为删除的数据,可能会影响某些特定场景下的性能表现;此时可以根据具体情况评估是否有必要定期清理旧有的无用记录或是调整索引策略以提升访问速度[^5]。 #### 4. 维护注意事项 随着系统的长期运行,累积下来的“假死”数据可能会逐渐增多,进而影响到整个系统的响应时间和资源利用率。因此建议设立合理的生命周期管理规则,并配套相应的自动化工具来进行周期性的整理工作,确保既能保存必要的审计痕迹又不会造成不必要的负担。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值