存储过程中支持/反对Business Logic的参数

时间:2009-01-27 18:04:23

标签: stored-procedures business-logic

存储过程中支持和反对业务逻辑的参数是什么?

18 个答案:

答案 0 :(得分:34)

针对存储过程:编程空间中的业务逻辑

我高度重视表达的力量,我发现SQL空间并不具备表达能力。使用您手头上最好的工具来完成最合适的任务。摆弄逻辑和高阶概念最好在最高级别完成。因此,存储和海量数据操作最好在服务器级别完成,可能在存储过程中完成。

但这取决于。如果您有多个应用程序与一个存储机制交互,并且您希望确保它保持其完整性和工作流,那么您应该将所有逻辑卸载到数据库服务器中。或者,准备好管理多个应用程序中的并发开发。

答案 1 :(得分:23)

我彻底反对它。其中一个最大的原因是Earino说的第一个原因 - 它生活在一个地方。您无法轻松地将其集成到源代码管理中。几乎不可能有两个开发人员同时处理存储过程。

我的另一个主要抱怨是SQL在表示复杂逻辑方面不是很好。你没有范围的概念,代码往往被复制粘贴,因为重用代码的能力较低(而不是OO语言)。

您必须让开发人员访问数据库才能在那里进行开发。在许多组织中,我曾在数据人员处于与开发人员不同的世界,具有不同的权限等。在这些情况下将开发人员排除在数据库之外会更难。

答案 2 :(得分:19)

我认为,只要是商业逻辑,我就是思想学派:

  • 住在一个的地方
  • 正确记录的地方
  • 通过可以松散耦合的服务提供适当的访问
  • 通过已发布的抽象界面

我不关心逻辑是存在于存储过程,J2EE中间层,剪辑专家系统中还是存在于任何地方。无论你在哪里存储我们的业务逻辑,“苦难保护法”都将保证有人会说这是错误的想法,因为组件/存储库X需要换掉技术/方法Y.

答案 3 :(得分:13)

一些想法:请注意这是一个以Java为中心的回复,但它是我近期(过去10年)的大部分经历

(1)(大型)开发团队的并行开发。如果你的应用程序足够复杂,每个开发人员都无法建立他们自己的私有版本的数据库(有参加的链接/参考数据/等...),很难让整个开发团队的TEAM全部工作存储在共享DEVL DB中的同一组PL-SQL(例如)包是什么?然后你的卡住(我的经验)在数据库中工作,无法执行程序/代码与表格不匹配,因为人们会做出更改......

作为一名Java架构师,我认为让每个开发人员在他们的桌面上拥有一个私有JBoss实例并轻松地在他们自己的功能集上工作,并按照自己的进度集成而不影响其他人...我... ...

(2)持续集成工具集 虽然在DB世界中存在一些类似的“概念”,但我的经验告诉我(我在这里选择我目前最好的优势)的组合:

  • mvn - 构建系统
  • junit - 自动化单元测试
  • nexus - repo manager(管理工件的生命周期版本,快照和发布)
  • hudson - ci build server
  • 声纳 - 静态分析工具/代码覆盖率报告/ ALOT 更

使用上述所有(免费工具)运行大型项目,可以通过一致/简便的方式向大众提供XP,并对整个IT员工实施质量控制。 Oracle / PL-SQL没有匹配的工具集

(3)工具/库/等... Java可以访问其他平台无法触及的一组惊人服务 - 一些是免费的,一些不是。 甚至是基本的,比如log4j(是的,它们用于PL / SQL,但是它们......它几乎不一样)允许允许开发人员创建灵活可调的日志记录,可以即时更改(非常适合dubugging) 。自动API文档(通过javadoc)。自动化单元测试覆盖率报告。令人难以置信的IDE(Eclipse),集成了调试器/自动部署到应用服务器。用于与sun下的各种服务进行交互的API,用于执行ANYTHING的开源库以及每个供应商的100%支持

(4)重用服务。有人评论的是真的。如果您拥有重型数据驱动的业务规则,那么您可以争辩说这些应该存在于数据库层中。为什么?防止中间层都必须复制该逻辑。

但对于不是数据驱动或足够复杂的业务规则,OO是更自然的选择,也可以这样说。如果您在数据库中粘贴所有业务逻辑,那么它们只能通过数据库使用。

  • 如果您希望在客户端或中间应用层中完成验证并保存到DB的往返,该怎么办?
  • 如果要缓存中间层中的只读数据(性能)并针对缓存数据执行业务规则,该怎么办?
  • 如果您的中间层服务不需要数据库访问,或者您的客户端可以提供自己的数据,该怎么办?
  • 如果业务规则的数据相关部分需要访问外部服务,该怎么办?然后,您将看到如下所示的零碎业务逻辑:

retCode = validateSomeDate(date);
if (retCode == 1) then
   evaluateIfCustomerGetsEmail(...)//probably more stored proc invocations here...
   sendEmailMsg(....)
else if (retCode == 2) then
   performOtherBizLogicStuf(...) //again, may need data, may not need data
   triggerExternalsystemToDoSomething(...) //may not be accessible via PL/SQL 
fi

我确信我们所有人都看到过如上所述的系统,并且必须在凌晨2点进行调试。当业务逻辑在层之间分散时,很难获得对复杂过程的一致感,并且在某些情况下,它无法维护。

答案 4 :(得分:11)

“您无法轻松地将其集成到源代码管理中。” - 如果您将创建存储过程的代码放入受版本控制的脚本中,则该异议就会消失。如果您遵循Scott Ambler的敏捷数据库想法,那正是您应该做的。

并非所有开发人员都是优秀的数据建模人员。我可以想到开发人员创建的可怕模式,他们认为SQL的知识使他们成为数据库专家。我认为开发人员使用DBA和数据建模器有很多价值。

如果只有一个应用程序使用数据库,我会说业务逻辑可以出现在中间层。如果许多应用程序共享数据库,也许最好将它放在数据库中。

SOA提供了一种中间方式:服务拥有自己的数据。只有服务才能访问数据;获取数据意味着通过服务。在这种情况下,可以将规则放在任何一个地方。

应用程序来去匆匆,但数据仍然存在。

答案 5 :(得分:8)

不在sprocs中存储业务逻辑的另一个原因 - 数据库的扩展能力有限。数据库是你的瓶颈是很常见的情况,这就是为什么尽可能多地加载数据库是个好主意。

答案 6 :(得分:7)

我的一些观察:

赞成存储过程:

  • 在项目生命的一段时间后,在大多数情况下,瓶颈是数据库而不是Web服务器 - 并且存储过程更快,更快

  • 使用sql profiler与ORM生成的sql查询非常困难;使用存储过程很容易

  • 您可以立即部署存储过程的修补程序,而无需服务窗口

  • 为了提高性能,优化存储过程比ORM代码更容易

  • 您可能有许多应用程序使用相同的db / stored procs

  • 任何复杂的数据场景都是对存储过程的投票

赞成申请/ ORM:

  • 您可以使用代码存储库(存储过程仍然可以,但价格昂贵)

  • java / c#language是表达业务逻辑的更好工具

  • java / c#更容易调试(动态生成的ORM sql除外)

  • 数据库引擎的独立性(但项目不太可能 将数据库更改为另一个)

  • ORM提供易于使用的数据模型

在我看来:对于大型项目 - 去存储过程,对于其他项目 - 应用程序/ ORM将正常工作。

在一天结束时,唯一重要的是数据库。

答案 7 :(得分:5)

业务逻辑应该封装在一个地方。我们可以保证逻辑始终运行并始终如一地运行。使用涉及数据库上的实体的所有活动必须运行的类,我们可以保证所有验证都正确运行。这个代码有一个地方,项目上的任何开发人员都可以轻松打开这个类并查看逻辑(因为文档可以并且确实已经过时,代码是唯一可靠的文档形式)。

这对存储过程很难处理。您可能有多个sproc处理相同的表。将多个sprocs链接在一起以便逻辑只驻留在一个中变得难以操作。这是一个打击。如何确定数据库中“实体X周围的所有业务规则是什么”?有趣的搜索成千上万的sprocs试图跟踪它。

第二,您将业务逻辑与持久性机制联系起来。您可能不会将所有数据存储在同一个数据库中,或者某些数据可能存在于XML等中。开发人员很难这种类型的不一致。

如果逻辑仅驻留在数据库中,则很难执行验证。你真的打电话给sproc来验证你的数据输入表格上的每个字段吗?验证规则和业务逻辑是近亲。这个逻辑应该都在同一个地方执行!

答案 8 :(得分:4)

+:SQL服务器有时会优化代码

+:您被迫传递参数,这限制了SQL注入问题

- :您的代码依赖于单个数据库(某些dbs甚至没有SP)

- :更改您需要连接数据库的代码

- :逻辑组织不好

我个人反对它,但我必须在一个非常繁忙的网站上使用它一次。在MS SQL中使用SP带来了巨大的好处,但是一旦我实现了缓存,那些好处就不再那么大了。

答案 9 :(得分:4)

有一种说法......

当你拥有的只是一把锤子时,一切看起来都像钉子。

根据我的拙见,没有一个适合所有情况的答案。在我看来,许多人只是假设将Business Logic放入数据库总是错误的。

在数据库端完成交易处理(尤其是批量操作)时,已经做了很多工作。此外,由于大多数针对数据库的意见形成,数据库中的代码管理也得到了极大的改进。

我认为将数据库服务器视为持久层是错误的。如果您在DB Server上完成处理活动效率最高,那么请在那里进行。

如果没有,那么在别处做。

这一切都归结为最适合您目前正在使用的应用程序,与您合作的团队以及雇用您的客户。

那只是我的2美分。

答案 10 :(得分:2)

您可以在业务逻辑层中对业务逻辑进行单元测试。如果它是完全独立的,则可以模拟持久性操作,因此您只测试BL。存储过程比维护/调试/单元测试要困难得多。 linq和c#。

答案 11 :(得分:1)

DBMS!=应用程序服务器

  • 功能编程(DB存储过程)与OOP。对于大型项目而言,OOP只是标准。
  • IDE - eclipse,intellij,netbeans以及用于调试,测试和分析的所有插件仅适用于真正的编程语言。 Static code tools
  • 版本控制,如果你得到一个PLSQL&合。是很棒的。如果你得到"同步视图"直接从你的IDE - 你是真正的幸运者。
  • 扩展您的系统。对于DB系统来说很糟糕。您需要昂贵的硬件用于其他节点"。复制。并且可能是每个节点的许可证。不要忘记你还在进行功能编程"并且努力理解和维护这样的系统要大得多。
  • 您被数据库困住,尝试更改或添加来自其他公司的新数据
  • 依旧......

业务逻辑的存储过程今天是不好的做法。改为使用3层架构。

答案 12 :(得分:0)

@Nick“我完全反对它。其中一个最大的原因是earino说的第一个原因 - 它存在于一个地方。你不能很容易地将它集成到源代码控制中。几乎不可能拥有两个开发者同时处理存储过程。“

并非我在争论将业务逻辑放在存储过程上(相反)。但是你提出的这些理由毫无意义。存储过程只是一个sql / DDL工件,可以存储在源代码控制中,也是一个部署工件(也就是说,移植到dba进行部署的东西,就像你交出你的战争/耳朵一样) IT /部署工具上的工件)一个或多个开发人员可以使用与原始源代码相同的方式处理源代码控制的相同存储过程 - 通过分支,版本控制和合并。

现在,如果存储过程的唯一副本(以及包含它们的包)仅存在于数据库中,那么显然您无法使用源代码控制(以及与之关联的所有问题)来控制它。但是,这不是存储过程的问题,而是关于如何使用该代码的无能问题。它同样也是一种无能的表现,因为只有一个源代码副本存在于制作中。

我曾在拥有大量代码的系统中工作,包括Java和PLSQL / DDL,它们都是在clearcase上进行版本化的。它们都被视为源代码,将使用严格的流程进行编译和部署,不同的团队正在处理它们。从来没有像你所描述的那样有任何问题。

特定于上下文的理由不将业务逻辑放在存储过程中,但这些逻辑不是有效的。

答案 13 :(得分:0)

通过将逻辑移入存储过程中可以大大提高性能,尤其是在涉及显式事务的情况下。

根据我的经验,应用程序开发人员不擅长编写优化的数据库代码,也不倾向于考虑并发或性能问题。
如果业务逻辑保留在应用程序层中,您往往必须在网络上移动大量数据(通常在多次往返中),在数据库服务器上的内存中复制,并且至少在应用服务器中复制一次,并在您持有开放交易时在应用程序中执行逐行处理。然后,应用程序开发人员抱怨数据库速度很慢并且一直处于死锁状态。

如果你把逻辑放在数据库中的任何地方,你往往只是在网络上传递一些参数,在等待网络资源时不会保持交易,整个过程就像闪电一样。 数据库当然应该像任何其他源代码一样进入源代码管理中。有很多工具可供使用。

答案 14 :(得分:0)

高预算项目:如果要在内存中保留最新数据并定期将更改保存到磁盘,则需要处理除数据库服务器之外的业务逻辑。用例:从ram,复杂的缓存机制提供数据。

低预算项目:如果要在磁盘上保留最新数据,并且演示文稿依赖于磁盘读取,则在存储过程中处理业务逻辑可以节省开发时间。用例:从磁盘提供数据

答案 15 :(得分:0)

有各种各样的“业务逻辑”。考虑根据它与其他层或服务的关联方式对其进行分区。以下是MVC观点的一些经验法则:

a)在数据库(存储过程)中,如果它主要与数据相关,可以使用连接和相对简单的WHERE和SELECT子句来完成。

b)在控制器中,如果它主要是路由或调度相关;也就是说,在屏幕或资源选择方面进行更大规模的UI流量控制。

c)在模型或视图模型中,如果它涉及复杂或复杂的计算和/或条件。

d)在视图(例如Razor)中,如果它主要是显示问题,例如“友好”重新格式化并且实现起来相对简单。 (如果它很复杂,请考虑将其放在视图模型中。)

答案 16 :(得分:0)

我的经验法则是(一旦我通过思考这个问题就认识到它是什么),存储过程应包含确保数据库内数据完整性的代码,无论存储过程是禁止某些数据的插入,删除或修改,还是数据一致性所需的其他更改。业务逻辑,特别是不能在少数基于集合的操作中实现的逻辑,应在其他地方实现。数据库不是应用程序。数据库应该是关系和约束的最终授权者,即使业务规则也可以在其他地方实现,例如在用户界面代码中提供反馈,以减少Web服务器的回发或消除繁忙服务器上的不必要的攻击。有人可以争辩“数据一致性”是否包括复杂业务规则的复杂处理的结果,但是我认为一旦理解了上下文通常就很清楚。并非所有业务规则都被实现为数据关系或约束。并非存储过程中的所有操作都比在单独的进程中运行的代码要快,即使在跨网络的单独计算机上运行的进程中也是如此。我最近进行了一次演示,展示了SSIS中的许多操作,例如(INSERT INTO()SELECT FROM)在单独计算机上通过网络运行的SSIS中执行的速度要比在存储过程中运行的速度快(该操作还将结果插入数据库)跨网络)。这几乎是令人难以置信的结果(SSIS比原始SQL语句要快),并证明对任何性能问题的最佳优化的发现都来自现实(测试),而不是仅基于几个概念的逻辑。 (我们仍然必须根据经验教训来决定要测试什么。)(SSIS通过自动实现多线程和管道,使用BULK INSERT(即使未在原始SQL语句中未指定)并发送批处理来更快地执行。在一个线程上执行插入操作,同时在其他线程上创建其他大容量INSERT。在这种情况下,它的执行速度是原始SQL语句的两倍。)当我过去教编程和SQL Server课程时,PowerBuilder用户似乎有一条语句“ Native驱动程序提供了最快的数据访问权限”,尽管可能通过其他(他们无法识别)额外的解释来证明是正确的,但其背后的想法具有误导性。

答案 17 :(得分:-1)

有了所有这些微服务和微业务组件的意识形态,我们就领先于质疑放置我们的业务逻辑的正确位置。

即使意识形态被广泛接受,我们仍然有诱惑力,在某些情况下我们最终将一些决策和业务逻辑放入数据库中。值得一看的是为什么不应该这样做的详细答案,但是在宏观层面上,我建议考虑一个很好的理由,为什么它应该保留在存储过程中而不是在应用程序层中。

拥有反思想的过程将始终指导正确的决定。在决定之前先问这些问题:

  1. 如果我们将数据库从SQL更改为Mongo,该怎么办?
  2. 如果要公开获取数据(该数据库正在提供)的API并在顶部应用此业务逻辑怎么办?
  3. 对该业务逻辑进行单元测试?
  4. 如果我们更改此业务逻辑的条件,将涉及SDLC步骤吗?
  5. 如果在此业务逻辑中我们需要其他用户输入来进行决策怎么办?
  6. 如果它需要很高的计算能力(而不是数据处理)并且我们希望在单独的进程(或平台)上运行怎么办?

在所有情况下,不将任何逻辑(不仅仅是数据检索)放在业务逻辑中都是自然选择。