標籤:可維護性 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