Jpa实现逻辑删除
原创
©著作权归作者所有:来自51CTO博客作者wx630f300fec73f的原创作品,请联系作者获取转载授权,否则将追究法律责任
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;
}