一、先來說說,什麼是java中的Statement:Statement是java執行資料庫操作的一個重要方法,用於在已經建立資料庫連接的基礎上,向資料庫發送要執行的SQL語句。具體步驟: 1.首先導入java.sql.*;這個包。 2.然後載入驅動,創建連接,得到Connection介面的的實現對象 ...
一、先來說說,什麼是java中的Statement:Statement是java執行資料庫操作的一個重要方法,用於在已經建立資料庫連接的基礎上,向資料庫發送要執行的SQL語句。具體步驟:
1.首先導入java.sql.*;這個包。
2.然後載入驅動,創建連接,得到Connection介面的的實現對象,比如對象名叫做conn。
3.然後再用conn對象去創建Statement的實例,方法是:Statement stmt = conn.creatStatement("SQL語句字元串");
Statement 對象用於將 SQL 語句發送到資料庫中。實際上有三種 Statement 對象,它們都作為在給定連接上執行 SQL語句的包容器:Statement、PreparedStatement(它從 Statement 繼承而來)和CallableStatement(它從 PreparedStatement 繼承而來)。它們都專用於發送特定類型的 SQL 語句:Statement 對象用於執行不帶參數的簡單 SQL 語句;PreparedStatement 對象用於執行帶或不帶參數的預編譯 SQL 語句;CallableStatement 對象用於執行對資料庫已存儲過程的調用。
綜上所述,總結如下:Statement每次執行sql語句,資料庫都要執行sql語句的編譯,最好用於僅執行一次查詢並返回結果的情形,效率高於PreparedStatement.但存在sql註入風險。PreparedStatement是預編譯執行的。在執行可變參數的一條SQL時,PreparedStatement要比Statement的效率高,因為DBMS預編譯一條SQL當然會比多次編譯一條SQL的效率高。安全性更好,有效防止SQL註入的問題。對於多次重覆執行的語句,使用Prepared
Statement效率會更高一點。執行SQL語句是可以帶參數的,並支持批量執行SQL。由於採用了Cache機制,則預編譯的語句,就會放在Cache中,下次執行相同的SQL語句時,則可以直接從Cache中取出來。
PreparedStatement pstmt = con.prepareStatement("UPDATE EMPLOYEES SET name= ? WHERE ID = ?");
pstmt.setString(1, "李四");
pstmt.setInt(2, 1);
pstmt. executeUpdate();
那麼CallableStatement擴展了PreparedStatement的介面,用來調用存儲過程,它提供了對於輸入和輸出參數的支持,CallableStatement 介面還有對 PreparedStatement 介面提供的輸入參數的sql查詢的支持。
PreparedStatement: 資料庫會對sql語句進行預編譯,下次執行相同的sql語句時,資料庫端不會再進行預編譯了,而直接用資料庫的緩衝區,提高數據訪問的效率(但儘量採用
使用?號的方式傳遞參數),如果sql語句只執行一次,以後不再復用。
從安全性上來看,PreparedStatement是通過?來傳遞參數的,避免了拼sql而出現sql註入的問題,所以安全性較好。
在開發中,推薦使用 PreparedStatement
二、
本人的幾點淺見,各位大大不喜勿噴。
先說下這倆到底是幹啥的吧。其實這倆乾的活兒都一樣,就是創建了一個對象然後去通過對象調用executeQuery方法來執行sql語句。說是CreateStatement和PrepareStatement的區別,但其實說的就是Statement和PrepareStatement的區別,相信大家在網上已經看到過不少這方面的資料和博客,我在此處提幾點,大家看到過的,就當重記憶,沒看到就當補充~下麵開始談談他們的區別。
最明顯的區別,就是執行的sql語句格式不同。我們往上放兩段代碼來看看他們的區別把:
代碼背景:我們有一個資料庫,裡面有一個user表,有username,userpwd兩列。我們要查出這兩列的數據。
這是使用CreateStatement方法創建了stmt對象,再通過他查詢的一部分語句片段。
String sql = "select * from users where username= '"+username+"' and userpwd='"+userpwd+"'";
stmt = conn.createStatement();
rs = stmt.executeQuery(sql);
而下麵則是使用了PrepareStatement方法創建了pstmt對象,再通過這個對象查詢的一部分語句片段。
String sql = "select * from users where username=? and userpwd=?";
pstmt = conn.prepareStatement(sql);
pstmt.setString(1, username);
pstmt.setString(2, userpwd);
rs = pstmt.executeQuery();
相信寫到這,大家很多人就能看出來了,原來PrepareStatement跟Statement的主要區別就是把上面sql語句中的變數抽出來了。這就是我要說的第一大優點,PrepareStatement可以提高代碼的可讀性。
下麵說說第二點優點。ParperStatement提高了代碼的靈活性和執行效率。
PrepareStatement介面是Statement介面的子介面,他繼承了Statement介面的所有功能。它主要是拿來解決我們使用Statement對象多次執行同一個SQL語句的效率問題的。ParperStatement介面的機制是在資料庫支持預編譯的情況下預先將SQL語句編譯,當多次執行這條SQL語句時,可以直接執行編譯好的SQL語句,這樣就大大提高了程式的靈活性和執行效率。
最後但也是最重要的一個大大的比Statement好的優點,那就是安全!
你說啥?這還關安全啥事兒,那我給你一行代碼,你來給我說說這是幹嘛的。
String sql = "select * from user where username= '"+varname+"' and userpwd='"+varpasswd+"'";
stmt = conn.createStatement();
rs = stmt.executeUpdate(sql);
這是驗證用戶名密碼的,對吧。但要是我們把'or '1' = 1'當作密碼傳進去,你猜猜會發生啥。
select * from user where username = 'user' and userpwd = '' or '1' = '1';
發現了吧!這是個永真式,因為1永遠等於1。所以不管怎樣都能獲取到許可權。哇。這就壞咯!這還不是最壞的,你再看!
String sql = "select * from user where username= '"+varname+"' and userpwd='"+varpasswd+"'";
stmt = conn.createStatement();
rs = stmt.executeUpdate(sql);
依舊是這行代碼。這次我們把'or '1' = 1';drop table book;當成密碼傳進去。哇!又壞了!這次直接把表給刪了。但是,你如果用PrepareStatement的話就不會出現這種問題。你傳入的這些數據根本不會跟原來的數據有任何的交集,也不會發生這些問題。
對資料庫進行增刪改查的過程中的通用的流程:
(1)創建Connection對象、SQL查詢命令字元串;
(2)對Connection對象傳入SQL查詢命令,獲得PreparedStatement對象;
(3)對PreparedStatement對象執行executeUpdate()或executeQurey()獲得結果;
(4)先後關閉PreparedStatement對象和Connection對象。
可見,使用JDBC時,最常打交道的是Connection、PreparedStatement這兩個類,以及select中的ResultSet類。查閱Java API手冊可以瞭解其具體的意義和方法。
下麵引用的Java API的資料出自http://download.oracle.com/technetwork/java/javase/6/docs/zh/api/index.html。
Connection
java.sql
介面 Connection
- 所有超級介面:
- Wrapper
public interface Connectionextends Wrapper
與特定資料庫的連接(會話)。在連接上下文中執行 SQL 語句並返回結果。
Connection
對象的資料庫能夠提供描述其表、所支持的 SQL 語法、存儲過程、此連接功能等等的信息。此信息是使用getMetaData
方法獲得的。
PreparedStatemnt
java.sql
介面 PreparedStatement
- 所有已知子介面:
- CallableStatement
public interface PreparedStatementextends Statement表示預編譯的 SQL 語句的對象。
SQL 語句被預編譯並存儲在
PreparedStatement
對象中。然後可以使用此對象多次高效地執行該語句。
常用方法
boolean execute()
在此 PreparedStatement 對象中執行 SQL 語句,該語句可以是任何種類的 SQL 語句。
ResultSet executeQuery()
在此 PreparedStatement 對象中執行 SQL 查詢,並返回該查詢生成的 ResultSet 對象。
int executeUpdate()
在此 PreparedStatement 對象中執行 SQL 語句,該語句必須是一個 SQL 數據操作語言(Data Manipulation Language,DML)語句,比如 INSERT、UPDATE 或 DELETE 語句;或者是無返回內容的 SQL 語句,比如 DDL 語句。
ResultSet
java.sql
介面 ResultSet
- 所有超級介面:
- Wrapper
- 所有已知子介面:
- CachedRowSet, FilteredRowSet, JdbcRowSet, JoinRowSet, RowSet, SyncResolver, WebRowSet
public interface ResultSetextends Wrapper表示資料庫結果集的數據表,通常通過執行查詢資料庫的語句生成。