嵌套PreparedStatement的最佳实践是什么?
我有几个实例,其中一部分旧版 sql 语句基于依赖项。 例如。
if (x !=null)
{
SQL = "SELECT z WHERE x > y";
}
else
{
SQL = "SELECT z WHERE x <= y";
}
SQL2 = SQL + " JOIN a ON b";
我正在根据这个遗留代码创建PreparedStatements。 这里的最佳实践是什么。 我应该为var SQL 创建一个PreparedStatement 并将其嵌套在SQL2 中,还是应该有多个基于SQL2 且没有嵌套的PreparedStatement,还是完全不同的东西?
该代码比示例复杂得多,因为 SQL var 在许多长且复杂的 SQL 查询中重用。
编辑:项目设计需要使用PreparedStatements,我目前没有使用库的选择。
I have several instances where that a section of legacy sql statements is based on a dependency. for example.
if (x !=null)
{
SQL = "SELECT z WHERE x > y";
}
else
{
SQL = "SELECT z WHERE x <= y";
}
SQL2 = SQL + " JOIN a ON b";
I am creating PreparedStatements out of this legacy code. What is the best-practice here. Should I create a PreparedStatement for the var SQL and nest it inside of SQL2 of should there be multiple PreparedStatements based on SQL2 without nesting, or something totlly different?
The code is much more complex than the example, as the SQL var is reused inside many long and complex SQL queries.
EDIT: Project Design requires using PreparedStatements, I don't have the choice of using libraries at this moment.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
>我应该为 var SQL 创建一个PreparedStatement 并将其嵌套在 SQL2 中吗
否
>或者是否应该有多个基于 SQL2 且不嵌套的PreparedStatement
是
此外:如果您可以为每个查询创建一个字符串,这样会更好。 我真的不喜欢将 SQL 与代码混合在一起。 它使调试和理解变得更加困难,您无法复制/粘贴到 SQL 工具来轻松测试它。 通过将 SQL 与代码分离,您可以将查询与操作(实际的获取)隔离开来,并且更容易维护。 另外,如果代码不是您的,它会更容易理解。
看起来重复字符串并不重要,重点是尽可能简化语句。
我会做这样的事情:
然后从你的类中使用它:
在创建类“DatabaseQueries”时,你会发现你重复了很多字符串,我认为用其他常量替换某些部分会很好。
这里的重点是让事情变得更简单。 这是第一步。 在第二步中,您可以创建一个类来创建那些非常非常复杂的查询,但可能是 YAGNI。
如果查询太多,您可以替换它以从 ResourceBundle 加载它们,如下所示 问题
我希望这有帮助。
>Should I create a PreparedStatement for the var SQL and nest it inside of SQL2
No
>Or should there be multiple PreparedStatements based on SQL2 without nesting
Yes
Furthermore: If you could create one string per query that would be better. I don't really like to mix SQL with code. It makes it harder to debug and to understand, you can't copy/paste to a SQL tool to test it easily. By separating the SQL from your code you'll isolate your query from the operation ( the actual fetch ) and it would be easier to maintain. Plus if the code is not yours it will be a lot easier to understand.
It doesn't matter it looks like your're repeating strings, the point would be to simplify the statements as much as possible.
I would do something like this:
And then use it from your class:
While creating the class "DatabaseQueries" you'll find you're repeating a lot of strings, I think it would be fine to susbtitute some part with other constants.
The point here is to make things simpler. This is the first step. In a second step you can create a class to create those queries that are really really complex, but probably YAGNI.
If the queries are too much you can replace it to load them from a ResourceBundle like in this question
I hope this helps.
Ibatis 非常擅长这一点。
这只是 Ibatis 功能的一小部分,但它非常轻量级。 技术精湛。
Ibatis is very good at this.
This is but a small fraction of what Ibatis can do but its extremely lightweight. Excellent technology.
这不是准备好的语句参数的正确使用方式。 参数只能用于代替 SQL 表达式中的文字值。 不是表名、列名或其他 SQL 语法。
您可以使用一些库来构建 SQL 查询的一部分。 我在 PHP 中开发了一个类似的库,名为
Zend_Db_Select< /代码>
。
编辑:我在 google 上搜索了一些类似的 Java 库,发现这个选项可能会有所帮助:
它是免费的,并根据 Apache 许可证提供,这是一个非常灵活的开源许可证。
谷歌搜索“java query builder”发现了许多其他选项,但有些不是免费的。 有些是可视化查询构建器,而不是编程式查询构建器。
另一种选择是使用复杂的对象关系映射框架(如 Hibernate),但这对于您当前的任务来说似乎有些过分了。
This is not the proper use of prepared statement parameters. Parameters can be used only in place of a literal value in an SQL expression. Not table names, column names, or other SQL syntax.
You could use some library for building parts of an SQL query. I worked on a library like this in PHP, called
Zend_Db_Select
.edit: I googled a bit for a similar library for Java, and I found this option which may be helpful:
It's free and offered under the Apache License, which is a pretty flexible open-source license.
Googling for "java query builder" found a number of other options, but some were not free. Some were visual query builders, not programmatic query builders.
Another option is to use a complicated object-relational mapping framework like Hibernate, but this seems overkill for your current task.
这是类似的问题
简短的回答 - 没有最好的办法。 你可能会得到这样的结果:
但对我来说,情况更糟。
Here is similar question
Short answer - there is no best way. You may end up with something like this:
But to me it is even worse.
我想一方面有一种纯粹的对象方法,如果您试图理解遗留代码,这可能对您没有太大帮助。 我发现,在重构真正令人讨厌的遗留代码时,而不是追求“完美”,简化小片段通常更好、更容易,尽可能模块化和有据可查,而无需立即重写整个应用程序。 我发现重构坏代码对我来说最大的障碍是,如果我采取太大的步骤,我就不能再确信我没有破坏任何东西 - 如果它那么糟糕,可能就没有单元测试,并且可能存在未定义或未记录的行为。
我至少会首先分解逻辑和 sql。 您不想要的事情是这样的:
一段时间后您将无法知道正在构建哪些语句。 节省复制初始 sql 的时间是不值得的。 它可能更容易理解为:
然后创建一些东西来包装您的查询和传递的参数,如 Spring JDBC Row Mappers 或类似的东西。 这仍然很丑陋,但是作为您所拥有的增量步骤,它很容易做到,并且至少会解决查询生成的一些混乱。
I guess on one hand there's a purist object approach, which is probably not going to be terribly helpful to you if you're trying to make sense of legacy code. I've found that in refactoring really nasty legacy code rather than striving for "perfect" it's often better, and easier, to simplify small pieces, as modular and well documented as you can make them without rewriting the entire app at once. I've found that the biggest hurdle for me in refactoring bad code is that if I take too large steps I can't any longer be confident that I haven't broken anything - if it's that bad, there are probably no unit tests, and there's likely undefined or undocumented behavior.
I'd at least break out the logic and the sql as a first pass. The thing you don't want is something like this:
After a while you won't be able to tell what statements are being built. It's not worth saving the bit of duplicating the initial sql. It might be easier to understand as :
and then just create something to wrap your queries and parameters passed like Spring JDBC Row Mappers or something similar. This is still ugly, but it's easy to do as an incremental step from what you've got, and will at least sort out some of the confusion of query generation.
另一种方法是将条件移至 SQL 语句本身,这样您只需要一个语句。 它会是这样的:
然后为参数绑定一个适当的值。
不确定这是最好的方法......人们可能会发现代码不太清晰。 但这是一种可能性。
Another approach would be to move the conditional into the SQL statement itself so you only need one statement. It would be something like:
and then bind an appropriate value for the parameter.
Not sure it's the best approach ... people might find the code less clear. But it is a possibility.