2

我正在这里加速一些缓慢的操作,一个案例是表中的父子关系树。目前系统运行在 SQLServer 上,经过一番研究,我发现使用通用表表达式可以将多个查询压缩为一个。

到目前为止一切都很好,但是语法是特定于 SQLServer 的,并且使用(例如)Oracle 做同样的事情需要完全不同的语法。

可以做些什么来构建系统以允许将来适应其他 RDBMS?我主要担心的是:

  • SQL 语句散布在代码中,一个 RDBMS 中的一条语句可能需要在另一个 RDBMS 中使用多个语句,因此甚至程序逻辑也可能需要更改。
  • 即使可以很好地封装在一个 RDBMS 中的东西(我正在使用存储函数来隐藏 DB 中的一些复杂性)在不同的 DB 中也有细微的差异,或者根本不可用。

到目前为止,我觉得超出最简单 SQL 语句的所有内容似乎总是需要特定于供应商的扩展,因此不可能将差异整齐地隐藏在几个类/存储的 SQL 中(当然可以使用具有大部分抽象已经内置了。但这也排除了数据库的许多更有用的特性)。

有哪些策略可以至少缓解供应商差异带来的痛苦?我知道这是一个非常广泛的问题,没有万能的答案。但我希望有一些指针和模式来减少数据库对应用程序的影响。

编辑:实现语言是 Java,简单地使用 ORM(例如 Hibernate)不是我想要的(或多或少需要重写约 50% 的代码库)。

EDIT2:我主要寻找以尽可能普遍兼容的方式将细节推送到数据库中的可能性,理想情况下我希望java部分使用的SQL对于所有平台都是相同的(或者只需要非常由于语法差异而略有变化)。对于我给出的 CTE 示例,我目前将其推送到存储函数中,希望在需要移植时,该功能也可以在函数中重现。

EDIT3:目前我没有迫切需要支持其他 RDBM。如果它只适用于 SQLServer,没有人会责怪我。但在可能的情况下,我希望避免将 java 代码与特定的数据库供应商联系起来。

EDIT4:一些背景 - 当前的工作是向系统添加功能 - 它不是设计或计划的功能。业务人员的要求一点点滴滴出现,很难提前计划。虽然每个需求本身并不是很难解决,但恐怕我们会积累一大堆标记的东西,如果不详细了解每个查询,这些东西是不可能移植的。由于 SQLServer 本身在每个主要的新版本中也引入了各种与自身不兼容的问题,我担心即使切换到更新的 SQLServer 也可能成为未来的主要障碍(我们过去从 2005 年到 2008 年进行过一次这样的升级 - 那一次去了对于我正在维护的东西来说很顺利,但它已经给我们的供应商之一造成了许多问题)。

4

4 回答 4

0

您没有指定您正在使用的应用程序平台。但我会假设您使用的是 .Net 或 Java。您的第一道防线是在应用程序的 SQL 语句中使用 ODBC 或 JDBC 转义序列,并将此方法无法处理的任何内容推送到存储过程中。

如果您拥有对应用程序进行更彻底重构的许可,则应考虑为您的应用程序平台切换到 ORM 库。

编辑:我看到您编辑了您的问题,澄清您正在使用 Java 并且切换到 ORM 库不是一种选择。很久以前,我正在为大型企业客户开发产品。每个客户都有自己的标准参考架构,因此我们必须适应 Oracle、Microsoft SQL Server 和 UDB/DB2。我们可能支持其他平台,但有些细节在 10 到 12 年后确实会变得模糊。我们通过对时间常数、函数和存储过程调用虔诚地使用 JDBC 转义以及将更敏感的操作推送到特定于数据库的存储过程中来实现这一点。所以我可以根据我的经验告诉你这种方法是有效的。目前,通过一系列收购,该产品是 Oracle 中间件产品组合的一部分,所以我不

我的另一个经历是在一个大数据仓库项目上。在这种情况下,我们大量使用了 Oracle 特定的特性,以至于根本无法选择迁移到另一个数据库平台。

因此,我的建议是评估使用 SQL Server 的特定功能是否是您的应用程序所固有的。如果是这样,您应该接受,如果不进行重大重写,就不能选择迁移到另一个平台。如果不是,请查看您是否可以通过使用 JDBC 转义来改进您对 SQL 的了解。

于 2012-07-18T13:06:14.270 回答
0

鉴于您使用的是遗留代码,我会选择一个接口,最初是一个实现,为每个与数据库相关的函数(例如 SaveOrder)添加方法,该函数采用一个简单的类,例如 Order :) ,或者在推送数据集时。随着你的进展,加入更多的东西,直到你所有的 sql 都在实现中,并且所有使用它的东西都通过接口。

然后,当您想在另一个数据库或其他持久层(如 NoSQL、Xml 或 ORM)上实现时,您知道自己必须做什么,并且还拥有一系列单元测试。

于 2012-07-18T13:27:57.293 回答
0

您可能会考虑使用 MyBatis 框架。MyBatis 将 SQL 查询和结果集映射到 Java 对象中,它还对 DB 特定的查询生成提供了一些支持。放入现有应用程序非常轻量级,并且可能会大大减少您的总代码行数。查看他们文档中关于多数据库供应商支持的部分,以获取演示该功能的快速示例映射文件。

于 2012-07-18T14:02:39.850 回答
0
  1. 远离 ORM。它们在项目中确实有其用途,但是如果您只想要数据库独立性,那就像您只需要一把锤子和一些钉子时就购买了一家General Factory Factory。

  2. 将您的数据访问层隔离在一组接口后面。您的代码库中的任何内容都不应该依赖于数据库,而是这些接口的实现。因此,这些实现之外的任何类都不应访问类路径中带有“jdbc”、“jpa”或“hibernate”的任何内容。您可以考虑使用 JDepend 或 DependencyFinder 编写实际测试。

  3. 使您当前的数据库访问实现这些接口。

  4. 拥有针对实际数据库运行并准备针对一组不同数据库运行的自动化测试。

  5. 当您必须支持第二个数据库时,修改您的测试以针对这两个数据库运行。使接口实现成为原始实现的副本,然后修复失败的测试。

  6. 现在查看您的两个实现并找到值得提取的内容并相应地重构您的代码。

如果您尝试将步骤 6 在链中进一步向上移动,您将遇到 YAGNI 和 WrongAbstractionException 的不良情况。

如果您决定使用任何类型的 ORM 或其他一些数据库访问技术,则适用相同的规则。

于 2012-07-18T15:29:33.113 回答