【发布时间】:2008-12-19 22:07:13
【问题描述】:
我目前正在做一个项目,其中代码中有大约 3000 行的 SQL 字符串。
该项目是一个java项目,但这个问题可能适用于任何语言。
无论如何,这是我第一次看到这么糟糕的事情。 代码库是遗留的,所以我们可以突然迁移到 Hibernate 或类似的东西。
你如何处理这样非常大的 SQL 字符串?
我知道这很糟糕,但我不知道最好的解决方案是什么。
【问题讨论】:
标签: java sql coding-style
我目前正在做一个项目,其中代码中有大约 3000 行的 SQL 字符串。
该项目是一个java项目,但这个问题可能适用于任何语言。
无论如何,这是我第一次看到这么糟糕的事情。 代码库是遗留的,所以我们可以突然迁移到 Hibernate 或类似的东西。
你如何处理这样非常大的 SQL 字符串?
我知道这很糟糕,但我不知道最好的解决方案是什么。
【问题讨论】:
标签: java sql coding-style
在我看来,将这些硬编码的值放入存储过程并从代码中引用存储过程可能是高产出和低工作量。
【讨论】:
SQL 是否有很多用于变量的字符串连接?
如果没有,您可以提取它们并将它们放入资源文件中。但是您必须删除换行符中的字符串内容。
您使用的存储过程方法非常好,但有时当需要了解 SQL 在做什么时,您必须从工作区切换到您喜欢的 SQL IDE。这是唯一的坏事。
我的建议是这样的:
String query = "select ......."+
3000 lines.
到
ResourceBundle bundle = ResourceBundle.getBundle("queries");
String query = bundle.getString( "customerQuery" );
就是这样。
【讨论】:
我想第一个问题是,你应该用它做什么?如果它没有坏,就悄悄地把它合上,假装你从未见过它。否则,像疯了一样重构——希望某处有一些类似于合同的退出条件。
【讨论】:
到目前为止,我能想到的最好的办法是将查询放入多个存储过程中,就像我在 Java 中处理过长的方法一样。
【讨论】:
我和你在同一个地方...我的计划是将 SQL 提取到项目中的单独 .sql 文件中,并创建一个实用方法来在我需要查询时读取文件。
string sql = "select asd,asdf,ads,asdf,asdf,"
+ "from asdfj asfj as fasdkfjl asf"
+ "..........................."
+ "where user = @user and ........";
查询被转储到一个名为usageReportByUser.sql的文件中
然后变成这样。
string sql = util.queries("usageReportByUser");
确保以不公开访问文件的方式完成。
【讨论】:
使用框架iBatis
【讨论】:
我为此写了一个toolkit,并在几个项目中使用了它。它允许您将查询放在大部分文本文件中,并为它们生成绑定和文档。
查看this example 和example use(它几乎只是一个编译成具有早期绑定/类型安全查询绑定的java 类的准备好的语句)。
它也会生成一些不错的 javadocs,但我目前没有在线文档。
【讨论】:
我赞同 iBatis 的建议。至少,您可以从最可能使用 StringBuffer 的 Java 代码中提取 SQL,并将其附加或 String concat 到 XML 中,这样更易于维护。
我为旧版 Web 应用程序执行此操作,然后打开调试并为 DAO 运行单元测试,并将为每个语句生成的 sql 复制到 iBatis xml 中。工作很顺利。
【讨论】:
我在 PHP 中所做的是:
$query = "SELECT * FROM table WHERE ";
$query .= "condition < 5 AND ";
$query .= "condition2 > 10 AND ";
然后,一旦你在 $query 上完成分层:
mysql_query($query);
【讨论】:
一种简单的方法是将它们分解为某种常量。这至少会使代码更具可读性。
【讨论】:
我将它们存储在文件(或资源)中,然后在应用启动时读取并缓存它们(如果它是服务或其他东西,则在更改时)。
或者,只需将它们作为 consts 或 readonlys 放入一个大的旧 SqlQueries 类中。
【讨论】:
我已经成功地将大型动态查询转换为 linq 查询。 (1K 行+)这非常适用于在相对较少的表格上进行大量动态过滤和动态分组的报告方案。为这些表创建一个 edmx,您可以编写出色的强类型可组合查询。
我发现性能实际上得到了提高,生成的 sql 也简单了很多。 我敢肯定你会用 Hibernate 获得类似的里程 - 除了能够使用 linq 当然。但一般来说,如果生成的 sql 需要高度动态,那么它不适合存储过程。在存储过程中编写动态 sql 是两全其美的。 sql 生成框架将是我去这里的首选方式。如果您挖掘 Hibernate,我认为这将是一个很好的解决方案。
话虽如此,如果查询只是带有参数的简单字符串,那么只需将它们放入存储过程中即可完成。 - 但是你错过了与对象一起工作的结果。
【讨论】: