软删除是一种广泛应用于业务应用程序的模式。它允许您将某些记录标记为已删除,而无需从数据库中实际删除。有效地,可以防止选择软删除的记录,同时,所有旧记录仍可以引用该记录
什么时候使用软删除有意义? 如果您随机询问一些开发人员,则很可能您会听说软删除用于恢复已删除的记录。但是,如果这是唯一促使您集成软删除的业务需求,请三思而后行。在决定在项目中使用软删除之前,除了“简单数据还原”之外,还请考虑以下要求:
实现软删除很容易!您只需将“ Is_Deleted”或“ Delete_Date”列添加到表(或文档的属性)中,并替换应用程序代码中的所有delete语句调用即可进行更新。是的,您需要修改所有检索语句以考虑此新属性。还是创建视图更好?还是物化视图?在这种情况下,我们可能需要实现“代替”触发器或存储过程API来处理视图。通过删除实体,您可能希望删除其引用的某些属性。在这种情况下,为了能够还原,还需要存储删除上下文。而且……这就是开发人员的生活变得复杂的地方。
软删除的挑战 实际上,实现“适当的”软删除并非易事。有时,开发人员选择不实施软删除,只是因为这需要很多工作。您可能会想到其他选项,例如带有特殊“垃圾箱”表的表镜像,该表包含“原始”表中的已删除记录。
但是,如果决定继续执行软删除实现,则需要考虑一些条件。
数据库支持。标记为已删除的记录的问题之一是它们的唯一键。举例来说-我们需要将用户及其电子邮件存储在一起。电子邮件必须是唯一的,因此,我们需要为存储用户的表创建唯一的索引。如果删除了一个用户,我们应该可以使用相同的电子邮件插入一个新用户。因此,您的数据库应该能够处理此类情况。选项之一-在唯一键中包含一个软删除标记字段。如果您的标记字段不是简单的布尔值,而是删除时间戳,则可以解决问题。
另一个选择-特殊的唯一索引。例如,在PostgreSQL中,它被称为部分唯一索引,在MSSQL过滤的索引中,它被称为。它们允许您通过指定谓词在构建索引时不考虑某些行。因此,对于软删除功能实现,我们可以从索引中排除“已删除”记录。
如果数据库支持视图触发器,则很有可能可以使用视图和instead of触发器类型创建数据模型。但是这种方法会影响性能,并且无法通过对基础表应用唯一约束来解决此问题。
应用支持。确保所有提及软删除实体的查询都经过仔细检查,否则可能导致意外的数据泄漏和严重的性能问题。在理想情况下,开发人员不应意识到软删除的存在。因此,如果可能,请尝试引入您的数据访问API,并防止开发人员使用其他工具来访问数据库(例如直接JDBC连接)。您甚至可能要覆盖标准的API,例如JPA的Entity Manager,以正确支持软删除。
重新使用标准API。首先,忘记使用某些标准的DB和JPA功能。如果您已经精心设计和调整了数据库表和约束模型以及JPA层,那么引入软删除要求您考虑以下事项:
CUBA平台中的软删除实施 CUBA平台支持开箱即用的软删除功能,并提供软删除功能,作为默认应用程序行为的一部分。在大多数情况下,开发人员不必担心是否使用软删除。CUBA中的数据操作API与众所周知的JPA API相同,为99%。你,作为一个开发者,可以使用EntityManager的remove()甚至是随心所欲的使用JPQL来处理应用程序中的数据。
在后台,CUBA平台拦截对EntityManager和JPQL查询的所有调用,并根据应用程序设置转换它们。该框架将承担繁重的工作,并提供正确的应用程序行为:“已删除”记录将不受更新影响,DELETE语句将转换为UPDATE并且SELECT不会获取“已删除”数据。
该实现基于三个主要支柱:
SoftDelete
EntityManager
delete
update
JoinExpressionProvider
SoftDeleteJoinExpressionProvider
这在大多数情况下都有效,但是在这个世界上没有完美的事物。为了灵活起见,CUBA仍然允许您执行本机SQL并获得对基础DataSource对象的访问。因此,即使使用解决了许多软删除实现问题的框架,您也需要仔细检查低级查询。
结论 即使对一个实体使用软删除,也会带您一堆新的开发约定。您需要记住,删除过程不仅是删除,而且有时更新和并非数据库表中的所有数据都可用于该应用程序。这意味着您应该对代码进行设计,使其在所有应用程序层中都将所有因素都考虑在内-从数据库架构(文档结构等)到用户界面(甚至如此)。使用适当的框架,您将能够解决所有这些问题,但您仍应记住,您已经“删除”了仍然存在的数据,并建立了将这一点考虑在内的编码标准和约定。
原文链接:http://codingdict.com