【问题标题】:Design Problem - Generating SQL Queries for business calculations设计问题 - 为业务计算生成 SQL 查询
【发布时间】:2010-12-10 09:11:03
【问题描述】:

我们有一个应用程序,允许用户输入表达式以对数据库表的字段执行计算。计算允许各种类型的函数(数学、逻辑、字符串、日期等)。例如 MAX(col1, col2, col3)。 请注意,这些表达式可能会因嵌套函数而变得复杂。例如 IF(LENGTH(StringColumn)=0, MAX(col1, col2, 32), MIN(col1, col2, col3)) > LENGTH(col2)

我们实现这一点的一种方法是使用 java cc 解析器来解析用户输入的表达式,然后生成树型数据结构。然后在 java 中解析树,并为表达式中使用的每个函数生成 sql 查询。最后,在为每个用户输入的表达式生成查询之后,java 使用简单的数据库调用来执行这个查询。

这个框架的一个主要问题是数据库问题要在java中处理。数据库问题是指一些数据库限制或任何性能优化。 Microsoft SQL Server 的一个数据库限制是只允许 10 个嵌套的 CASE WHEN 语句。这意味着在解析 java 代码时需要估计查询字符串在翻译之前有多少个 CASE WHEN。 同样,如果要进行任何 sql 性能优化,在 java 中处理它们根本不合逻辑。

有人知道解决这个问题的更好的设计方法吗?

【问题讨论】:

    标签: java sql


    【解决方案1】:

    让您的用户使用 SQL 查询数据库,而不是重新实现一种非常类似于 SQL 的语言来转换为 SQL。

    【讨论】:

    • 这是软件提供的功能。软件用户的技术水平不足以了解 SQL 语言。他们正在提供我上面提到的业务功能。例如MAX(column1,column2) 等数学函数。然后需要将这些函数转换为 sql 查询,然后执行预期的计算。
    • 你的语言比SQL还复杂!您甚至很少看到开发人员写像IF(LENGTH(StringColumn)=0, MAX(col1, col2, 32), MIN(col1, col2, col3)) > LENGTH(col2) 这样的东西,但您的“业务用户”正在写它。如果他们能写,他们就可以写 SQL!他们甚至不必学习专有语言;他们受益于数十年的文档、示例和工具。我希望您在指定应用程序时至少游说反对创建此系统。
    • 我不是设计应用程序规范的功能团队的一员。鉴于我提到的需要提供功能,您认为有没有更好的方法来实现此功能。
    【解决方案2】:

    我会研究 Hibernate 和它的 HQL 查询语言。

    作为对上述海报的回应,我认为让您的用户直接使用 SQL 查询数据库是个坏主意,因为您将面临 SQL 注入攻击。

    【讨论】:

    • 这些不是休眠映射对象。应用程序提供的功能是允许用户对表中的数据进行计算。正如我所提到的,计算意味着业务功能。用户可以输入表达式,然后由软件解析以执行预期的计算。此过程的输出是另一个包含计算数据的数据表。
    • 您可以允许直接 SQL 访问,而无需打开自己的注入。这就是数据库模型的几层专用——访问控制、外部视图。您创建只读视图,或者不授予他们连接的用户修改不应修改的内容的权限。
    【解决方案3】:

    前段时间我写了一个带有动态过滤例程的java小程序,在那里我将sql语句转换为javascript语句并使用javascripts exec函数执行它们

    【讨论】:

    • “使用 javascripts exec 函数执行”是什么意思?查询需要针对数据库运行。
    【解决方案4】:

    您可以查看 JPA 2.0 Criteria API 或 Hibernate Criteria API

    • JPA 2.0 提供了所谓的 Criteria API (http://stackoverflow.com/questions/2602757/creating-queries-using-criteria-api-jpa-2-0)
    • Hibernate 有自己的 Criteria API(甚至在 JPA 2.0 之前) - 但它与 JPA 2.0 Criteria API 不同。 (http://www.ibm.com/developerworks/java/library/j-typesafejpa/)

    这两个 Criteria API 的目的是提供一种在运行时创建 sql 查询的方法,这种方法比连接字符串更令人愉快。 (http://docs.jboss.org/hibernate/core/3.3/reference/en/html/querycriteria.html)

    (JPA 2.0 Critiera API 有一个额外的功能,它提供了某种代码生成,这使得以节省编译时间的方式编写查询成为可能。(http://docs.jboss.org/hibernate/core/ 3.3/reference/en/html/querycriteria.html))

    【讨论】:

    • 计算将在不是休眠映射对象的数据库表上执行。因此这种可能性不成立对吧?
    【解决方案5】:

    我能想到的另一种方法是寻找数据库支持的语言识别器(在我的例子中是 Oracle)。类似于我们目前在 java 中使用的(即 javacc),如果数据库支持类似的框架,则可以解析中间字符串并将其转换为 sql 查询。 我在这里引用的中间字符串与用户输入的字符串相似,但可能完全相同(例如,列名可以转换为实际的物理列名)。

    对这种方法有什么想法(优点和缺点)?此外,对于 Oracle 中的语言识别器的任何建议,我们将不胜感激。

    谢谢。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-07-31
      • 1970-01-01
      • 1970-01-01
      • 2011-01-28
      • 1970-01-01
      • 1970-01-01
      • 2011-12-08
      相关资源
      最近更新 更多