在没有预准备语句的情况下防止SQL注入(JDBC)

我有一个数据库日志appender,每隔一段时间就会将可变数量的日志行插入到数据库中。

我想以防止SQL注入的方式创建一个SQL语句,但不使用服务器端预处理语句(因为我在每个选择中都有可变数量的行,缓存它们不会有帮助,但可能会损害性能) 。

我也喜欢准备好的陈述的便利,并且更喜欢他们串起来。 有没有像“客户端准备好的声明”?

听起来你没有对最简单的解决方案 – 准备好的语句进行基准测试。 你说他们“可能会损害性能”,但在你测试之前,你真的不会知道。

肯定会先测试准备好的陈述。 即使它们确实会稍微妨碍性能,在您测试它们之前,您也不会知道您是否仍能达到所需的性能。

当你没有尝试过最明显的解决方案时,为什么要花时间寻找替代解决方案呢?

如果您发现准备好的语句执行计划缓存成本很高,您可能会发现存在特定于DB的调整或禁用它的方法。

不确定我是否正确理解你的问题。 PreparedStatement中有什么东西不适合您的需求吗?

我认为该语句是否在服务器端缓存是数据库驱动程序和您正在使用的特定数据库的实现细节; 如果您的查询/语句随时间变化而不会产生影响 – 则不会使用缓存/编译语句。

首先,Jon的回答是,在性能被测量为问题之前,你应该采用最明显的解决方案,这当然是正确的方法。

我不认为您的性能问题是错误的。 我确实看到预编译的复杂语句在性能规模上显着失败(在MS-SQL 2000上)。 原因是语句非常复杂,根据参数有几个潜在的执行路径,但是编译为一组参数锁定了一个,而下一组参数太慢,而重新编译会强制重新计算执行计划更适合不同的参数集。

但是,直到你在实践中看到它,这种担忧是非常遥远的。

这里的根本问题是参数转义是特定于数据库的,所以除非你的数据库的JDBC驱动程序给你一些非标准的东西(非常不可能),你将不得不拥有一个不同的库或不同的转义机制,这个数据库是非常具体的。

从您的问题的措辞来看,这听起来并不像您的性能问题已经到了值得寻找(或开发)这样一个解决方案的程度。

还应该注意的是,尽管JDBC驱动程序可能并非都是这样,但从技术上讲,根据规范,预编译应该在PreparedStatement对象中缓存,如果你把它丢弃并且每次都得到一个新的PreparedStatement,它不应该实际上是缓存任何东西,所以整个问题可能是静音的,需要针对您的特定JDBC驱动程序进行调查。

从规格:

可以预编译带有或不带IN参数的SQL语句并将其存储在PreparedStatement对象中。 然后,可以使用此对象多次有效地执行此语句。

使用常规预处理语句有什么问题,例如在以下伪代码中:

 DatabaseConnection connection; PreparedStatement insertStatement = ...; ... connection.beginTransaction(); for (Item item : items) { insertStatement.setParameter(1, item); insertStatement.execute(); } connection.commitTransaction(); 

智能数据库实现将多​​个插入批处理到与数据库服务器的一个通信交换中。

我想不出你不应该使用准备好的陈述的原因。 如果您使用连接池在J2EE服务器上运行此服务器,则服务器会保持连接打开,并且服务器会缓存您的访问/执行计划。 这不是它缓存的数据!

如果您每次都关闭连接,那么您可能无法获得任何性能。 但是你仍然可以获得SQL注入预防

大多数java性能调优书都会告诉你相同的: Java性能调优

准备好的语句不关心客户端或服务器端。

使用它们并删除任何SQL字符串连接。 没有一个理由不使用准备好的陈述。