java - 检查对象是否被引用,以防止在不修改数据库的情况下软删除

标签 java hibernate jpa reference soft-delete

如您所见,我在系统上使用软/逻辑删除:

我的实体:

@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 使用已删除标志恢复已删除的记录,恢复只是翻转标志。使用存档表,恢复工作会更加繁重:

  1. 从存档中选择
  2. 插入数据表
  3. 从存档中删除

如果无法修改数据库

如果数据库无法更改,则必须在 DAO 类内完成这些检查(您需要调用所有相关实体的查询)。最好确保所有数据库访问都通过这些类进行,否则(如果有人使用直接 SQL)您可能会遇到数据库不变量不成立的情况。

关于java - 检查对象是否被引用,以防止在不修改数据库的情况下软删除,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50009441/

相关文章:

hibernate - JPA 存储库与实体职责

java - Querydsl native jpa查询返回实体而不是对象数组

java - 我想得到一些关于一只耳朵中多个 ejb-jar 的建议

java - JBoss AS 在 Mac OS 上无法启动?

java - 使用java中的规范解码二进制数据

java - Bean创建异常: Error creating bean with name 'userRepository' : Post-processing of merged bean definition failed

java - 带有数字和下一个、上一个的 Jpa 分页

java - 在俄罗斯方 block 游戏中正确使用 wait()/notify()

java - hibernate中这两种查询方式有什么区别?

hibernate 外键