Java 我们什么时候应该使用准备好的报表而不是报表?

Java 我们什么时候应该使用准备好的报表而不是报表?,java,database,prepared-statement,Java,Database,Prepared Statement,我知道使用PreparedStatement的优点,它们是 查询由数据库服务器重写和编译 针对SQL注入的保护 但是我想知道我们什么时候用它来代替语句 查询由数据库服务器重写和编译 如果你不使用事先准备好的 语句,数据库服务器将 必须解析并计算 语句的执行计划 每次你运行它。如果你发现 您将运行相同的语句 多次(使用不同的 参数)那么它值得准备 将语句删除一次并重用该语句 准备好的声明。如果你是 然后临时查询数据库 这样做可能没有什么好处 这个 防止SQL注入 这几乎是你的优势 总是想因

我知道使用
PreparedStatement
的优点,它们是

  • 查询由数据库服务器重写和编译
  • 针对SQL注入的保护
但是我想知道我们什么时候用它来代替
语句

  • 查询由数据库服务器重写和编译

    如果你不使用事先准备好的 语句,数据库服务器将 必须解析并计算 语句的执行计划 每次你运行它。如果你发现 您将运行相同的语句 多次(使用不同的 参数)那么它值得准备 将语句删除一次并重用该语句 准备好的声明。如果你是 然后临时查询数据库 这样做可能没有什么好处 这个

  • 防止SQL注入

    这几乎是你的优势 总是想因此有一个很好的理由 每次使用
    PreparedStatement
    。 这是不得不这样做的结果 参数化查询,但它确实 让它运行起来更安全。这个 这是我唯一能想到的 如果你是,那就没用了 允许临时数据库查询;你 你可以简单地使用这个语句 对象,如果您正在对 应用程序和它对您来说更快, 或者如果查询不包含 参数


  • 我想扭转这一局面:在一个公开发布的应用程序中,你通常应该始终使用准备好的语句,除非你有一个非常有说服力的理由不,并且你应该始终“正确”地向准备好的语句提供参数,而不是将它们拼接到查询字符串中


    为什么??好的,基本上是因为您给出的原因(或者至少是第二个原因).

    除了防止SQL注入、格式化可移植性(您无法从
    语句中获得)之外,性能是显而易见的原因。然而,
    PreparedStatement
    并不是没有任何惩罚的。例如,如果只运行一次,它通常比
    语句
    慢,因为会有一些开销。因此,一般的想法是,当您多次执行相同的查询时,应该使用
    PreparedStatement
    。然而,多少开销是特定于数据库服务器实现的,因此从性能考虑,选择
    PreparedStatement
    而不是
    Statement
    的确切时间应该基于您对特定数据库服务器的实际经验/实验。

    询问Tom: JDBC中语句的使用应该100%本地化为用于DDL(ALTER, CREATE、GRANT等),因为它们是唯一不能接受BIND的语句类型 变量

    其他类型的报表应使用PreparedStatements或CallableStatements (DML,查询)。因为这些是接受绑定变量的语句类型

    这是一个事实、一条规则、一条法律——在任何地方都要使用事先准备好的陈述。使用语句 几乎没有。

    他特别提到了Oracle,但同样的原则也适用于任何缓存执行计划的数据库

    同时扩展和防止SQL注入攻击的数据库应用程序?缺点是什么?

    在WHERE子句中应非常小心地使用准备好的语句

    假设表定义为:

    create table t (int o, k varchar(100), v varchar(100))
    
    (例如,“o:对象ID(外键)、k:属性键、v:属性值”)

    此外,v上还有一个(非唯一)索引

    create index ixt on t ( v )
    
    假设此表包含插入的2亿行,如:

    for (i = 0; i < 100*1000*1000; i++) {
      insert into t (o,k,v) values (i,'k1','v1');
      insert into t (o,k,v) values (i,'k2', Convert(i, varchar));
    }
    
    (“查找具有两个给定属性的对象”)

    我对ORACLE和MSSQL的经验是,这些查询可能需要很多分钟才能返回。即使没有与where子句匹配的行,也是如此。这取决于SQL Server决定先查找tx.v还是ty.v

    应该在语句中输入k和v directy列的值。我认为这是因为SQL服务器在计算执行计划时考虑了这些值

    如下所示的查询总是在毫秒后返回:

    select o,p,v from t as tx, t as ty where tx.o=ty.o and tx.k='k1' and tx.v='v1' and ty.k='k2' and ty.v='1234'
    
    (“SQL Server将始终首先搜索v='1234',然后搜索v='v1')

    问候

    Wolfgang

    语句:每次运行sql查询时,此sql语句都会发送到DBMS,并在其中编译。因此,它增加了服务器负载并降低了性能

    connection con=null; 
      String sql="select * from employee where id=5";
    Statement st=conn.createStatement();
    
    PreparedStatement:与语句不同,PreparedStatement在创建时作为参数提供sql查询

    connection con=null; 
    String sql="select * from employee where id=?";
    PreparedStatement ps=conn.prepareStatement(sql);
    
    此sql语句被发送到编译它的数据库。
    所以,in-preparedStatement只编译一次,而in-statement每次调用语句时都编译一次。

    您始终可以使用preparedStatement而不是station(选择、插入、更新、删除)。更好的性能和针对SQL注入的保护


    但是,不要将它与动态请求一起使用,例如带有[Cumbers Oblembies]中的
    WHERE变量的请求。

  • 这会适得其反,因为每次新请求时都会缓存,所以会损失性能和内存,而PreparedStatement不仅仅用于SQL注入,它还与性能有关。在这种情况下,语句不会变慢

  • 您的池有PreparedStation的限制(-1 defaut,但您必须限制它),您将达到此限制!若你们并没有限制或者限制非常大,那个么你们就有内存泄漏的风险,在极端情况下,还会发生内存错误。所以,如果你的个人小项目被3个用户使用,这并不引人注目,但如果你在一家大公司,你的应用程序被成千上万的人和百万的请求使用,你不希望这样

  • 一些阅读。

    这只是一个Java设计错误,将“prepared statement”与“参数化查询/绑定变量”绑定在一起

    数据库确实有API来接受SQL代码中只运行一次的“绑定变量”

    这是一个巨大的资源浪费,到处使用“事先准备好的声明”,只是为了p
    connection con=null; 
    String sql="select * from employee where id=?";
    PreparedStatement ps=conn.prepareStatement(sql);