对于那些已经或喜欢在存储过程中编写业务逻辑的人来说,使用这种方法的原因是什么呢?
我尽量在数据库中严格限制业务逻辑,仅使用必须进行大量查询和更新才能执行单个应用程序操作的存储过程。有些人可能会争辩甚至这些也应该在应用程序中处理,但如果可以减少IO操作,我更愿意将其留在数据库中。
数据库非常适合进行CRUD操作,但是如果它们被繁琐的逻辑所充斥:
仅将业务逻辑限制在应用层中,最多只是短视的。有经验的专业数据库设计人员很少允许其存在于系统中。数据库需要拥有约束、触发器和存储过程来帮助定义任何来源的数据如何进入其中。
如果要保持数据库的完整性并确保所有新数据或数据更改的来源都遵循规则,则必须将所需逻辑放置在数据库中。将其放在应用程序层中会导致数据问题的出现。数据库不仅从一个应用程序获得信息。应用程序中的业务逻辑通常会在导入时被意外忽略(假设您有一个新客户想要将其旧历史数据导入到您的系统中,或者一大批目标记录,没有人会通过界面输入数百万个可能的目标。它将在导入中处理),也会被通过查询窗口进行的更改而绕过以解决一次性问题(例如将所有产品价格增加10%的事情)。如果您有应该应用于数据更改的应用程序层逻辑,但没有应用该逻辑,那么它就无效了。现在将其放在应用程序层中也可以,没有必要将错误数据发送到数据库并浪费网络带宽,但不在数据库中添加此逻辑迟早会导致数据问题。
将所有这些内容保留在数据库中的另一个原因与用户可能会犯欺诈有关。如果您将所有逻辑都放在应用程序层中,那么您必须直接向表授权用户访问权限。如果您将所有逻辑封装在存储过程中,则可以限制它们仅执行存储过程允许的操作,而不做其他任何事情。我不会考虑允许用户以任何方式访问存储财务记录或个人信息(如健康记录)的数据库,就像我不会允许除几个数据库管理员之外的任何人直接访问生产记录一样。比许多开发人员意识到的更多的欺诈行为已经发生了,几乎没有人在他们的设计中考虑这种可能性。
如果需要导入大量数据,则通过数据访问层进行导入可能会减慢其速度,因为它未利用数据库旨在处理的基于集合的操作。
您对“业务逻辑”这个术语的使用比较模糊。
它可以被解释为包括对数据的约束执行(也称为“业务规则”)。对于这些的强制执行绝对应该在dbms中进行。
它也可以被解释为包括诸如“如果有新客户到来,那么在一周内我们会给他发送欢迎信。”之类的内容。试图将这种东西推入数据层可能是一个巨大的错误。在这种情况下,“创建新的欢迎信”的驱动程序应该是触发新客户行插入的应用程序。想象一下,每次新的数据库行插入都会触发一封新的欢迎信,然后突然我们接管了另一家公司并必须将该公司的客户集成到我们自己的数据库中……哎呀。
我们在数据库层面上进行很多处理,如果适当的话。有很多操作不适合将大型数据集拉回应用程序层面进行分析。这对我们来说也更容易部署 —— 一个单一的点 vs. 在所有安装点更新应用程序。但很多取决于你的应用程序及其所做的事情;这里没有单一的好答案。
有时我会在存储过程中加入“逻辑”,因为CRUD可能会发生在多个地方。所谓的“逻辑”并不是真正的业务逻辑,而是更多的“完整性逻辑”。它可能是相同的 - 如果以某种方式删除或更新某些内容,并且如果该删除或更新可以从具有不同代码库的多个工具中进行,则需要进行一些清理,将其放入所有工具都使用的存储过程中是有意义的。
此外,有时“业务逻辑线”非常模糊。以报告为例 - 它们可能依赖于封装了关于架构对业务意义的“智能”的存储过程或视图。您是否见过基于列值或其他标准“执行操作”的CASE语句等?这可能被解释为业务逻辑,但它确实属于可以进行优化等的数据库中。
将业务逻辑放在数据库中的两个好处是:
通常情况下,在数据库层中可以找到业务逻辑,因为在进行更改和部署时,这样做通常会更快。我认为,通常不是出于将逻辑放置在那里的最好意图,而是由于部署的便利性而导致它最终被放在那里。