Java 即使PreparedStatement的值始终相同,参数化它是否更好?

Java 即使PreparedStatement的值始终相同,参数化它是否更好?,java,sql,jdbc,sql-injection,Java,Sql,Jdbc,Sql Injection,我总是读博客,今天我在读文章。作者曾写过一篇关于查询参数化的文章,即使用API提供的参数化比连接字符串更好、更安全、更具性能,并使用以下示例: SQL查询1:带字符串连接的PreparedStatement String loanType = getLoanType(); PreparedStatement pstmt = conn.prepareStatement("select banks from loan where loan_type=" + loanType); SQL查询2:使用

我总是读博客,今天我在读文章。作者曾写过一篇关于查询参数化的文章,即使用API提供的参数化比连接字符串更好、更安全、更具性能,并使用以下示例:

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驱动程序将检查数据,如果驱动程序没有连接字符串,它将只运行发送的SQL,也就是说,如果我们有著名的或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");

另一个问题,在这种情况下,我认为安全问题是相同的,因为没有参数通过用户,所以没有攻击,对吗?

如果参数确实从未更改,那么使用文本是可以接受的。但是,根据数据库平台的不同,将参数值作为将要更改的文本传递可能会导致性能不佳

在准备语句时,数据库将解析SQL并创建一个执行计划,该计划是使用优化器定位结果的最佳方法。这可能涉及几个步骤,包括“硬”解析和“软”解析

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


当您使用嵌入的文本参数重复执行SQL语句时,数据库必须在每次执行时执行硬解析,因此;可能需要更多的处理时间

安全性是相同的。使用预处理语句的附加安全好处是,它验证用户输入,以防止SQL注入。如果没有用户输入,就没有安全风险


如果您想使用不同的数据多次进行类似的数据库调用,那么使用参数来使用单个Prepared语句比使用字符串连接为每个实例构建新的Prepared语句要高效得多。如果只是一次调用,那么我无法想象性能会受到多大的影响。

在多次使用同一语句和不同参数值的情况下,性能会有所提高,因为准备工作(包括数据库引擎对SQL语句的编译和优化步骤)只执行一次,至少在一些JDBC驱动程序/DB引擎中执行一次。如果您有一个不来自用户的固定值,则无需使用预先准备好的语句。无论是从性能的角度来看,还是从注入的角度来看,都不存在问题

主要优势,在我看来,使用PreparedStatement优于普通语句的唯一决定性优势是参数化查询,这样您就可以在运行时动态地接受查询,这是一个巨大的优势,当您需要最终用户对如何继续进行提供指导时。此外,PreparedStatement设计用于优化查询运行方式中的执行时间。简单语句将直接执行正在传递的查询。既然您使用的是PreparedStatement,我建议您使用问题中的选项2,作为使用“标记”动态传递参数?符号是使用PreparedStatement的优点


现在的问题是,如果参数值从未改变,您将如何处理?这只是一个意见问题。在这种情况下,我的建议是使用一个直接字符串作为查询,不要使用参数。

不幸的是,人们一直在向下投票,但没有解释原因。多可怜的孩子啊!