如何检查对象是否被引用,以避免未修改数据库时执行软删除?
搞定软删除的两个关键问题:引用检查+避免无效更新
嘿,我来帮你解决这个软删除的需求!你现在需要实现两个核心功能:一是防止删除被其他对象引用的Person,二是避免对已经标记为删除的对象重复执行数据库操作。结合你给出的现有代码,我整理了具体的实现方案:
第一步:先堵住无效更新的漏洞
首先,在你的DeletePerson方法里,先判断数据库里的对象是不是已经被软删除了,没必要再执行一遍save操作,浪费数据库资源:
@Override public ServiceResponse DeletePerson (Person entity) { ServiceResponse sr = new ServiceResponse<>(); try { sr = ValidateDeletePerson(entity); if (sr.hasError()) return sr; Person dbEntity = GetPerson(entity.getPersonID()); // 先检查是否已经是删除状态,直接返回提示 if (dbEntity.isDeleted()) { sr.setMessage("该人员已经被删除啦"); sr.setSuccess(false); return sr; } // 后面再做引用检查和删除操作 dbEntity.setDeleted(true); _repository.save(dbEntity); sr.setSuccess(true); sr.setMessage("删除成功"); } catch (Exception ex) { sr.setSuccess(false); sr.setMessage("删除失败:" + ex.getMessage()); } return sr; }
第二步:实现引用检查逻辑
接下来要检查这个Person是不是被其他实体引用了,分两种常见场景来处理:
场景1:一对一/一对多的直接关联(比如关联了订单、地址)
假设你的系统里有Order实体关联了Person,你可以通过对应的Repository查询有没有未删除的关联记录:
// 先在PersonService里注入OrderRepository(其他关联实体的Repository同理) @Autowired private OrderRepository orderRepository; // 写个专门的方法做引用检查 private ServiceResponse checkPersonReferences(Person person) { ServiceResponse sr = new ServiceResponse<>(); // 检查有没有未删除的订单关联这个Person boolean hasActiveOrders = orderRepository.existsByPersonIdAndDeletedFalse(person.getPersonID()); if (hasActiveOrders) { sr.setSuccess(false); sr.setMessage("这个人员还有关联的有效订单,不能删除哦"); return sr; } // 要是还有其他关联实体,比如Address、Contract,直接加类似的检查就行 // boolean hasActiveAddresses = addressRepository.existsByPersonIdAndDeletedFalse(person.getPersonID()); // if (hasActiveAddresses) { // sr.setSuccess(false); // sr.setMessage("该人员存在关联的有效地址,无法删除"); // return sr; // } sr.setSuccess(true); return sr; }
然后把这个检查方法加到DeletePerson里:
@Override public ServiceResponse DeletePerson (Person entity) { ServiceResponse sr = new ServiceResponse<>(); try { sr = ValidateDeletePerson(entity); if (sr.hasError()) return sr; Person dbEntity = GetPerson(entity.getPersonID()); if (dbEntity.isDeleted()) { sr.setMessage("该人员已经被删除啦"); sr.setSuccess(false); return sr; } // 先过一遍引用检查,有问题直接返回 sr = checkPersonReferences(dbEntity); if (sr.hasError()) return sr; // 没问题就标记删除并保存 dbEntity.setDeleted(true); _repository.save(dbEntity); sr.setSuccess(true); sr.setMessage("删除成功"); } catch (Exception ex) { sr.setSuccess(false); sr.setMessage("删除失败:" + ex.getMessage()); } return sr; }
场景2:多对多关联(比如Person和Role)
如果是多对多的关系,中间有个关联表(比如person_role),那你需要查询这个中间表有没有未删除的关联记录:
// 先写个自定义查询的Repository方法 public interface PersonRoleRepository extends JpaRepository<PersonRole, Long> { @Query("SELECT COUNT(pr) FROM PersonRole pr WHERE pr.person.id = :personId AND pr.deleted = false") long countActivePersonRoles(@Param("personId") Long personId); } // 然后在checkPersonReferences里加检查 boolean hasActiveRoles = personRoleRepository.countActivePersonRoles(person.getPersonID()) > 0; if (hasActiveRoles) { sr.setSuccess(false); sr.setMessage("这个人员还有关联的有效角色,不能删除"); return sr; }
可选:数据库层面加防护(额外保障)
要是担心有人直接操作数据库误删,你可以给外键加ON DELETE RESTRICT约束,但因为是软删除,这个需要配合触发器或者数据库层面的逻辑,不过代码层面的检查还是更灵活,建议以代码检查为主。
内容的提问来源于stack exchange,提问作者Pablo De Luca
相关产品推荐
相关产品推荐

