我应该对 Java 中的所有数据库插入使用PreparedStatements 吗?
在 Java 中将变量插入数据库之前转义变量的推荐方法是什么?
据我了解,我可以使用PreparedStatement.setString()来转义数据,但是如果我不打算再次运行相同的查询,PreparedStatement似乎有点不切实际。是否有更好的方法可以在不准备每个查询的情况下做到这一点?
What is the recommended method for escaping variables before inserting them into the database in Java?
As I understand, I can use PreparedStatement.setString() to escape the data, but PreparedStatement seems somewhat impractical if I don't plan to run the same query ever again.. Is there a better way to do it without preparing every query?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
是的,对所有事情都使用准备好的语句。
它们被解析一次。
它们不受 SQL 注入攻击。
它们是更好的设计,因为您必须考虑 SQL 及其使用方式。
它们是更好的设计,因为
如果您认为它们只使用一次,那么您就没有看到大局。 有一天,您的数据或您的应用程序将会改变。
编辑。
为什么准备好的语句会让您思考 SQL?
当您组装字符串(或只是执行文本文本块)时,您并没有创建新的
PreparedStatement
对象。 您只是执行 SQL —— 可以非常随意地完成。当您必须创建(并保存)一个
PreparedStatement
时,您必须多考虑一点关于封装和责任分配的问题。 语句的准备是执行任何 SQL 处理之前的有状态事件。额外的工作虽然很小,但并非微不足道。 这使得人们开始考虑 ORM 和数据缓存层以及类似的东西来优化他们的数据库访问。
使用准备好的语句,数据库访问不再是随意的,而是更加有意的。
Yes, use prepared statements for everything.
They're parsed once.
They're immune from SQL injection attacks.
They're a better design because you have to think about your SQL and how it's used.
If you think they're only used once, you aren't looking at the big picture. Some day, your data or your application will change.
Edit.
Why do prepared statements make you think about your SQL?
When you assemble a string (or simply execute a literal block of text) you aren't creating a new
PreparedStatement
object. You're just executing SQL -- it can be done very casually.When you have to create (and save) a
PreparedStatement
, you have to think just a tiny bit more about encapsulation, allocation of responsibility. The preparation of a statement is a stateful event prior to doing any SQL processing.The extra work is small, but not insignificant. It's what causes people to start thinking about ORM and a data caching layer, and things like that to optimize their database access.
With Prepared statements, database access is less casual, more intentional.
您永远不应该使用字符串连接自己构建 SQL 查询。 构建 SQL 查询时,切勿手动转义变量/用户数据。 实际所需的转义取决于您的底层数据库,并且在某些时候有人会忘记转义。
要点是:使用准备好的语句,不可能创建 SQL 可注入语句。 通过自定义转义,这是可能的。 选择是显而易见的。
You should never construct a SQL query yourself using string concatenation. You should never manually escape variables/user data when constructing a SQL query. The actual escaping that is required varies depending on your underlying database, and at some point somebody WILL forget to escape.
The point is this: with prepared statements, it is impossible to create a SQL injectable statement. With custom escaping, it is possible. The choice is obvious.
准备一份声明并不那么昂贵。 它比大多数替代品更安全。
Preparing a statement isn't that expensive. It's safer than most of the alternatives.
我听说过这样的论点:PreparedStatement 比普通的 Statement 花费了一些额外的开销,并且如果我不将用户输入连接到查询中,它应该是安全的。 这可能是真的,但额外的成本并没有那么多,而且 SQL 查询会随着时间的推移而变化。 如果您今天开始使用语句,因为您已经向自己证明您的查询是防注入的,那么当维护程序员更改 SQL 以接受用户输入但不接受用户输入时,您就会陷入失败。考虑将该Statement更改为PreparedStatement。 我的建议是始终使用PreparedStatement 来避免麻烦出现。
I've heard the argument that PreparedStatement costs a little extra overhead over a plain Statement, and that it should be safe if I'm not concatenating user input into my query. This may be true, but the extra cost isn't that much, and SQL queries change over time. If you start out using a Statement today because you've proven to yourself that your query is injection-proof, you're setting yourself up for failure on the day that a maintenance programmer changes the SQL to accept user input, but doesn't think to change that Statement to a PreparedStatement. My advice is to always use a PreparedStatement to head off trouble before it finds you.
更好的是,不要直接使用 JDBC API,因为它很容易出错(例如,在所有情况下都无法正确清理所有资源)。 使用 JDBC 帮助程序对象(例如 Spring 的 JdbcOperations 接口),这可以显着减少代码的大小和错误。 如果您仅使用 Spring 来实现这一功能,那么与直接使用 JDBC API 相比,您仍然帮了自己很大的忙。
Even better, don't use the JDBC API directly, because it's so error-prone (e.g. failing to properly clean up all resources in all cases). Use a JDBC helper object such as Spring's JdbcOperations interface, which considerably reduces the size and bugginess of your code. If you only use Spring for this one feature, you've still done yourself a massive favour compared to using the JDBC API directly.