2014-02-14 25 views
0

我总是阅读博客Java Revisited,今天我正在阅读文章Why use PreparedStatement in Java JDBC - Example Tutorial。在一个点上笔者写了关于查询的参数,那就是更好的,更安全,更表演使用API​​提供比来连接字符串的参数,并使用下面的例子:即使值始终相同,参数化PreparedStatement是否更好?

SQL查询1:PreparedStatement的使用字符串连接

String loanType = getLoanType(); 
PreparedStatement pstmt = conn.prepareStatement("select banks from loan where loan_type=" + loanType); 

SQL查询2:使用PreparedStatement的

PreparedStatement pstmt = conn.prepareStatement("select banks from loan where loan_type=?"); 
pstmt.setString(1, loanType); 

笔者解释说,通过使用参数,JDBC驱动程序将检查数据和连接字符串司机d参数化查询它不会运行发送的SQL,即如果我们有着名的OR 1 = 1,查询将始终返回true,并且有经典的SQL注入情况。

我不清楚的是,为什么一个人比另一个更具表现力,再加上,如果我的价值总是相同的,这是真的吗?

PreparedStatement pstmt = conn.prepareStatement(select * from users where active = 'S'); 

或者是更多表演用途如下:

PreparedStatement pstmt = conn.prepareStatement(select * from users where active = ?); 
pstmt.setString(1, "S"); 

另一个问题是,在这种情况下,我认为安全问题是一样的,因为没有参数,通过用户传递有没有攻击,对吧?

+1

不幸的是,人们在不解释原因的情况下保持低调。多么可怜! –

回答

4

如果参数确实没有改变,那么使用文字是可以接受的。但是,根据数据库平台的不同,将参数值作为文字传入将会导致更改,这可能会导致性能不佳。

当您准备语句时,数据库将解析SQL并创建执行计划,以找到结果的最佳方式(使用其优化程序)。这可能涉及几个步骤,包括“硬”解析和“软”解析。

当您准备带有参数化值的语句时,数据库将解析SQL并缓存解析的执行计划。然后,您可以多次执行准备好的语句,并且只更改要发送到数据库的参数值。数据库可以重新使用缓存的执行计划,而不必再'硬'解析SQL。

当您使用嵌入式文字参数重复执行SQL语句时,数据库必须对每次执行执行硬解析,因此;潜在更多的处理时间。

1

安全性是一样的。使用Prepared Statements的附加安全优势是验证用户输入以防止SQL注入。在没有用户输入的情况下,不存在安全风险。

如果要使用不同数据多次调用类似的数据库,使用参数使用单个Prepared Statement而不是使用字符串连接为每个实例构建新的Prepared Statement会更加高效。如果这只是一次性电话,那么我无法想象性能会受到很大影响。

1

由于准备工作(包括数据库引擎对SQL语句的编译和优化步骤)只能执行一次,因此在多次使用不同参数值的情况下可以获得性能提升 - 至少在一些JDBC驱动程序/数据库引擎中。如果您的修正值不是来自用户,则不需要使用准备好的语句。从性能角度来看,也没有注入问题。

1

使用PreparedStatement而不是普通Statement的主要优点是参数化查询 - 这样你就可以在运行时动态地接受查询了(这对你来说是一个巨大的优势需要终端用户就如何继续进行指导)。另外,PreparedStatement被设计用来优化运行查询的执行时间。简单语句将直接执行传递的查询。因此,由于您使用的是PreparedStatement,因此我建议您使用选项2(从您的问题开始)使用'markers'(?符号)动态传递参数是使用PreparedStatement的优势。

现在,如果参数值永远不会改变,那么您该如何继续下去 - 这只是一个意见问题。在这种情况下,我的建议是使用直线字符串作为查询并且不使用参数。

相关问题