如您所见,我在系统上使用软/逻辑删除:
我的实体:
@Where(clause = "deleted='false'")
public class Person {
//...
}
我的服务:
@Override
public ServiceResponse DeletePerson (Person entity) {
ServiceResponse sr = new ServiceResponse<>();
try {
sr = ValidateDeletePerson(entity); //Business logic treatment
if (sr.hasError())
return sr;
Person dbEntity = GetPerson(entity.getPersonID());
dbEntity.setDeleted(true);
_repository.save(dbEntity);
} catch (Exception ex) {
sr.getErrors().add(new ServiceError(ex));
}
return sr;
}
当用户尝试删除一个对象时 - 实际上只有 boolean 值deleted在数据库上切换为true,正如我上面演示的那样 - 我想 在执行此逻辑删除之前,检查该对象是否被引用到另一个对象。
因此,如果该对象正在被其他人使用/引用,我想将此操作捕获为错误,或进行其他类似的处理以防止删除。
例如,如果ID 5
的人附加到学生
,则用户无法删除此人。
防止这种情况发生的“最佳实践”是什么?
重要编辑:
1)Person在N个表中被引用,而不仅仅是在Student上,所以我正在研究一种通用的方法来实现它(也许你可以告诉hibernate检查它?)
2)这个想法是以编程方式进行的,避免对数据库进行修改。
最佳答案
您可以在数据库级别使用检查约束。详细信息是特定于 DBMS 的,但约束的总体思路是
CHECK ((select count(*) from studens
where studens.id= person.id and person.deleted=false) = 0)
其他解决方案 - 归档表
您可以通过删除记录并将删除的记录移动到 person_archive 表(数据库触发器可以为您做到这一点)来避免此问题。通过此解决方案,外键将能够保护数据完整性。如果您的 person
表很大,此解决方案也可能更有效,因为数据库必须读取更少的数据。
我会使用 person_archive 表,除非您需要轻松地从 UI 使用已删除标志恢复已删除的记录,恢复只是翻转标志。使用存档表,恢复工作会更加繁重:
- 从存档中选择
- 插入数据表
- 从存档中删除
如果无法修改数据库
如果数据库无法更改,则必须在 DAO 类内完成这些检查(您需要调用所有相关实体的查询)。最好确保所有数据库访问都通过这些类进行,否则(如果有人使用直接 SQL)您可能会遇到数据库不变量不成立的情况。
关于java - 检查对象是否被引用,以防止在不修改数据库的情况下软删除,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50009441/