惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

博客园 - Franky
N
Netflix TechBlog - Medium
宝玉的分享
宝玉的分享
Google DeepMind News
Google DeepMind News
腾讯CDC
G
Google Developers Blog
Martin Fowler
Martin Fowler
Microsoft Security Blog
Microsoft Security Blog
Recent Announcements
Recent Announcements
爱范儿
爱范儿
Engineering at Meta
Engineering at Meta
Microsoft Azure Blog
Microsoft Azure Blog
A
About on SuperTechFans
aimingoo的专栏
aimingoo的专栏
有赞技术团队
有赞技术团队
Jina AI
Jina AI
人人都是产品经理
人人都是产品经理
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
M
MIT News - Artificial intelligence
罗磊的独立博客
博客园 - 三生石上(FineUI控件)
美团技术团队
WordPress大学
WordPress大学
阮一峰的网络日志
阮一峰的网络日志

博客园 - 张占岭

keycloak~缓存对象的介绍与作用 wso2-apim-mcp2改版分析 mcp1和mcp2对比 为什么前端项目使用ts比js要多了 多个IDP的用户联合方案的分析 apisix~forward-auth外部认证 apisix~response-rewrite响应头重写 springboot~关于构造方法注入和字段注入的选择 apisix~OpenResty各阶段的介绍 keycloak~aud受众字段的作用及如何生成 wso2~关于workbuddy中mcp在wso2中的授权端点 k8s~避免调度资源碎片化 WEB安全~csrf介绍 WEB安全~DPoP的介绍 WEB安全~csp的介绍 什么是中间人攻击 WEB安全~xss的介绍 k8s~pod资源限制和JVM的XMX配置 关于对wso2和keycloak的token交换的调研 keycloak~实现OAuth 2.0 Token Exchange backstage~实体的介绍及它们的关系 backstage~openapi的接入与protobuf的对比 backstage~将java服务添加到backstage backstage~对接github和gitlab backstage~开始一个backstage应用 apisix~graphQL的支持 wso2几个核心项目介绍 docker~BuildKit的介绍 k8s~secret资源的使用 算法~时间戳计算两个日期是否为同天同时同分
springboot~jpa优雅的软删除能力
张占岭 · 2026-03-03 · via 博客园 - 张占岭

之前写过关于springboot~jpa优雅的处理isDelete的默认值的文章,今天说一下在jpa或者其它类型的Repository中实现软删除的方法,主要借助了自定义的仓储的能力。

优雅的引用方式

/**
 * 开启软删除的能力
 *
 * @author lind
 * @date 2025/9/8 11:24
 * @since 1.0.0
 */
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@EnableJpaRepositories(repositoryBaseClass = SoftDeleteRepositoryImpl.class)
public @interface EnableSoftDeleteRepository {

}

接口标准化

/**
 * 软删除能力,通过@EnableSoftDeleteRepository注解开启功能,通过接口继承的方式实现这个能力
 *
 * @param <T>
 * @param <ID>
 */
@NoRepositoryBean // 不让jpa使用代理建立实现类
public interface SoftDeleteRepository<T, ID> {

	T getEntityById(ID id);

	/**
	 * 希望重写findById方法
	 * @param id
	 * @return
	 */
	T getById(ID id);

}

覆盖默认的deleteById方法,实现软删除

/**
 * 自定义的公共仓储的实现
 *
 * @param <T>
 * @param <ID>
 */
public class SoftDeleteRepositoryImpl<T, ID> extends SimpleJpaRepository<T, ID> implements SoftDeleteRepository<T, ID> {

	private final EntityManager entityManager;

	private final JpaEntityInformation<T, ID> jpaEntityInformation;

	Class<T> domainType;

	Logger logger = LoggerFactory.getLogger(SoftDeleteRepositoryImpl.class);

	public SoftDeleteRepositoryImpl(JpaEntityInformation<T, ID> jpaEntityInformation, EntityManager entityManager) {
		super(jpaEntityInformation, entityManager); // 必须调用父类构造函数
		this.entityManager = entityManager;
		this.jpaEntityInformation = jpaEntityInformation;
		this.domainType = jpaEntityInformation.getJavaType();
	}

	@Override
	public T getEntityById(ID id) {
		return entityManager.find(this.domainType, id);
	}

	/**
	 * @param id
	 * @deprecated
	 */
	@Override
	public void deleteById(ID id) {
		logger.info("CustomRepositoryImpl.getById " + id);
		T entity = getEntityById(id);
		if (entity != null && entity instanceof DeletedFlagField) {
			((DeletedFlagField) entity).setDeletedFlag(1);
			entityManager.merge(entity);
		}
		else {
			super.deleteById(id);
		}
	}

}

需要实现软删除的仓库接口上,继承这个接口即有这个软删除的能力

/**
 * 用户仓储
 *
 * @author lind
 * @date 2025/7/15 15:56
 * @since 1.0.0
 */
public interface UserEntityRepository extends SoftDeleteRepository<UserEntity, String>,
		JpaRepository<UserEntity, String>, JpaSpecificationExecutor<UserEntity> {

}