【Java】PreparedStatement VS Statement

來源:互聯網
上載者:User

標籤:可維護性   new   方法   cas   get   result   sel   oid   select   

建立時:  

    Statement statement = conn.createStatement();
    PreparedStatement preStatement = conn.prepareStatement(sql); 

執行時:    

    ResultSet rSet = statement.executeQuery(sql);
    ResultSet pSet = preStatement.executeQuery();

由上可以看出,PreparedStatement有先行編譯的過程,已經綁定sql,之後無論執行多少遍,都不會再去進行編譯,

而 statement 不同,如果執行多變,則相應的就要編譯多少遍sql,所以從這點看,preStatement 的效率會比 Statement要高一些。

import java.sql.Connection;import java.sql.DriverManager;import java.sql.PreparedStatement;import java.sql.ResultSet;import java.sql.Statement;public class JDBCTest {        public static void main(String[] args) throws Exception {        //1 載入資料庫驅動        Class.forName("com.mysql.jdbc.Driver");                //2 擷取資料庫連接        String url = "jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=UTF-8";        String user = "root";        String password = "root";        Connection conn = DriverManager.getConnection(url, user, password);                //3 建立一個Statement        String sql = "select id,loginName,email from user where id=";        String tempSql;         int count = 1000;        long time = System.currentTimeMillis();        for(int i=0 ;i<count ;i++){            Statement statement = conn.createStatement();            tempSql=sql+(int) (Math.random() * 100);            ResultSet rSet = statement.executeQuery(tempSql);            statement.close();        }        System.out.println("statement cost:" + (System.currentTimeMillis() - time));                  String psql = "select id,loginName,email from user where id=?";        time = System.currentTimeMillis();          for (int i = 0; i < count; i++) {              int id=(int) (Math.random() * 100);              PreparedStatement preStatement = conn.prepareStatement(psql);            preStatement.setLong(1, new Long(id));              ResultSet pSet = preStatement.executeQuery();            preStatement.close();          }          System.out.println("preStatement cost:" + (System.currentTimeMillis() - time));          conn.close();    }    }

  上述代碼反覆執行,

statement cost:95           preStatement cost:90

statement cost:100         preStatement cost:89

statement cost:92           preStatement cost:86

當然,這個也會跟資料庫的支援有關係,http://lucaslee.iteye.com/blog/49292  這篇文章有說明

雖然沒有更詳細的測試 各種資料庫, 但是就資料庫發展 版本越高,資料庫對 preStatement的支援會越來越好,

所以總體而言, 驗證  preStatement 的效率 比 Statement 的效率高

2>安全性問題

這個就不多說了,preStatement是先行編譯的,所以可以有效防止 SQL注入等問題

所以 preStatement 的安全性 比 Statement 高

3>代碼的可讀性 和 可維護性 
這點也不用多說了,你看老代碼的時候  會深有體會

preStatement更勝一籌

 

1 、PreparedStatement 介面繼承 Statement , PreparedStatement 執行個體包含已編譯的 SQL 語句,所以其執行速度要快於 Statement對象。

2 、作為 Statement 的子類, PreparedStatement 繼承了 Statement 的所有功能。三種方法

      execute 、 executeQuery 和 executeUpdate 已被更改以使之不再需要參數

3 、在 JDBC 應用中 , 如果你已經是稍有水平開發人員 , 你就應該始終以 PreparedStatement 代替

      Statement. 也就是說 , 在任何時候都不要使用 Statement.

基於以下的原因 :

一 . 代碼的可讀性和可維護性 .

雖然用 PreparedStatement 來代替 Statement 會使代碼多出幾行 , 但這樣的代碼無論從可讀性還是可維護性上來說 . 都比直接用Statement 的代碼高很多檔次 :

stmt.executeUpdate("insert into tb_name (col1,col2,col2,col4) values (‘"+var1+"‘,‘"+var2+"‘,"+var3+",‘"+var4+"‘)");//stmt 是 Statement 對象執行個體

 

perstmt = con.prepareStatement("insert into tb_name (col1,col2,col2,col4) values (?,?,?,?)");

perstmt.setString(1,var1);

perstmt.setString(2,var2);

perstmt.setString(3,var3);

perstmt.setString(4,var4);

perstmt.executeUpdate(); //prestmt 是 PreparedStatement 對象執行個體

 

不用我多說 , 對於第一種方法 . 別說其他人去讀你的代碼 , 就是你自己過一段時間再去讀 , 都會覺得傷心 。

 

PreparedStatement 盡最大可能提高效能 .

    語句在被 DB 的編譯器編譯後的執行代碼被緩衝下來 , 那麼下次調用時只要是相同的先行編譯語句就不需要編譯 , 只要將參數直接傳入編譯過的語句執行代碼中 ( 相當於一個涵數 ) 就會得到執行 . 這並不是說只有一個 Connection 中多次執行的先行編譯語句被緩衝 , 而是對於整個 DB 中 , 只要先行編譯的語句文法和緩衝中匹配 . 那麼在任何時候就可以不需要再次編譯而可以直接執行 . 而 statement 的語句中 , 即使是相同一操作 , 而由於每次操作的資料不同所以使整個語句相匹配的機會極小 , 幾乎不太可能匹配 . 比如 :

insert into tb_name (col1,col2) values (‘11‘,‘22‘);

insert into tb_name (col1,col2) values (‘11‘,‘23‘);

即使是相同操作但因為資料內容不一樣 , 所以整個個語句本身不能匹配 , 沒有緩衝語句的意義 . 事實是沒有資料庫會對普通語句編譯後的執行代碼緩衝 。

當然並不是所以先行編譯語句都一定會被緩衝 , 資料庫本身會用一種策略 , 比如使用頻度等因素來決定什麼時候不再緩衝已有的先行編譯結果. 以儲存有更多的空間儲存新的先行編譯語句 .

三 . 最重要的一點是極大地提高了安全性 。

即使到目前為止 , 仍有一些人連基本的惡義 SQL 文法都不知道 .

String sql = "select * from tb_name where name= ‘"+varname+"‘ and passwd=‘"+varpasswd+"‘";

如果我們把 [‘ or ‘1‘ = ‘1] 作為 varpasswd 傳入進來 . 使用者名稱隨意 , 看看會成為什麼 ?

 

select * from tb_name = ‘ 隨意 ‘ and passwd = ‘‘ or ‘1‘ = ‘1‘;

因為 ‘1‘=‘1‘ 肯定成立 , 所以可以任何通過驗證 . 更有甚者 :

把 [‘;drop table tb_name;] 作為 varpasswd 傳入進來 , 則 :

select * from tb_name = ‘ 隨意 ‘ and passwd = ‘‘;drop table tb_name; 有些資料庫是不會讓你成功的 , 但也有很多資料庫就可以使這些語句得到執行 .

 

而如果你使用先行編譯語句 . 你傳入的任何內容就不會和原來的語句發生任何匹配的關係 。

只要全使用先行編譯語句 , 你就用不著對傳入的資料做任何過慮 。

而如果使用普通的 statement, 有可能要對 drop,; 等做費盡心機的判斷和過慮 。

【Java】PreparedStatement VS Statement

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.