• 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;
        }
  • 相关阅读:
    PAT1001
    关于yahoo.com.cn邮箱导入Gmail邮箱验证异常的机制解析及解决办法
    浙大机试感受
    PAT1002
    mysql修改密码后无法登陆问题
    Windows 不能在 本地计算机 启动 OracleDBConsoleorcl
    Deprecated: Function ereg_replace() is deprecated
    PHP中静态方法(static)与非静态方法的使用及区别
    微信小程序开发,weui报“渲染层错误”的解决办法
    Android系统下载管理DownloadManager功能介绍及使用示例
  • 原文地址:https://www.cnblogs.com/zouhong/p/14365880.html
Copyright © 2020-2023  润新知