随笔 - 832  文章 - 2  评论 - 31  阅读 - 167万

Jpa实现逻辑删除

Spring Data 是个好东西,极大简化了后端dao的操作,只需要在 dao 接口写个 findByXXX 的方法就能自动实现按条件查询这个简直太爽了。但是在实际使用过程中,可能会遇到一个持久化逻辑删除的问题。那么问题来了。spring data jpa并不支持逻辑删除。那如何处理?

 

在互联网项目中,通常删除都不是物理删除,而是逻辑删除

 

那么在展示数据的时候需要过滤掉已删除的数据。而@Where 注解可以说就是为此而设计的。

复制代码
package org.hibernate.annotations;

import java.lang.annotation.Retention;
import java.lang.annotation.Target;

import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

/**
 * Where clause to add to the element Entity or target entity of a collection.  The clause is written in SQL.
 * A common use case here is for soft-deletes.
 *
 * @author Emmanuel Bernard
 */
@Target({TYPE, METHOD, FIELD})
@Retention(RUNTIME)
public @interface Where {
    /**
     * The where-clause predicate.
     */
    String clause();
}
复制代码

 

 

 这玩意儿乍一看很美好。但是实际不然。这样做将所有的删除方法都覆盖了。当我想要用到物理删除的时候。就不能用了。于是再次出发。寻找一种更加美妙的解决方案。终于让我找到了。话不多说。直接放码。

复制代码
@NoRepositoryBean
public interface BaseDao<T extends BaseEntry, ID extends Serializable> extends PagingAndSortingRepository<T, ID> {
 
    @Override
    @Transactional(readOnly = true)
    @Query("select e from #{#entityName} e where e.deleted = false")
    List<T> findAll();
 
    @Override
    @Transactional(readOnly = true)
    @Query("select e from #{#entityName} e where e.id in ?1 and e.deleted = false")
    Iterable<T> findAll(Iterable<ID> ids);
 
    @Override
    @Transactional(readOnly = true)
    @Query("select e from #{#entityName} e where e.id = ?1 and e.deleted = false")
    T findOne(ID id);
 
    @Override
    @Transactional(readOnly = true)
    @Query("select count(e) from #{#entityName} e where e.deleted = false")
    long count();
 
    @Override
    @Transactional(readOnly = true)
    default boolean exists(ID id) {
        return findOne(id) != null;
    }
 
    @Query("update #{#entityName} e set e.deleted = true where e.id = ?1")
    @Transactional
    @Modifying
    void logicDelete(ID id);
 
    @Transactional
    default void logicDelete(T entity) {
        logicDelete((ID) entity.getId());
    }
 
    @Transactional
    default void logicDelete(Iterable<? extends T> entities) {
        entities.forEach(entity -> logicDelete((ID) entity.getId()));
    }
 
    @Query("update #{#entityName} e set e.deleted = true ")
    @Transactional
    @Modifying
    void logicDeleteAll();
}
复制代码

BaseEntry代码如下:

复制代码
    @Data
    @MappedSuperclass
    public class BaseEntry implements Serializable {
     
        private static final long serialVersionUID = 5966306766659220492L;
     
        @Id
        protected String id;
     
        @Temporal(TemporalType.TIMESTAMP)
        protected Date createdDate;
     
        protected String createdBy;
     
        @Temporal(TemporalType.TIMESTAMP)
        protected Date updatedDate;
     
        protected String updatedBy;
     
        protected Boolean deleted = false;
    }
复制代码

 

posted on   小破孩楼主  阅读(2689)  评论(0编辑  收藏  举报
编辑推荐:
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
历史上的今天:
2020-02-03 host文件的作用和介绍
2020-02-03 CentOS 查看系统 CPU 个数、核心数、线程数
< 2025年3月 >
23 24 25 26 27 28 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 1 2 3 4 5

点击右上角即可分享
微信分享提示