javajdbc預編譯res
㈠ 徹底搞懂JDBC的運行過程
前幾天筆者發布了博客,手寫mybatis徹底搞懂框架原理。為了幫助初學者更好理解mybatis框架,這次講解一下java的JDBC的運行過程。
JDBC的作用
JDBC的全稱是Java DataBase Connection,也就是Java資料庫連接,我們可以用它來操作關系型資料庫。JDBC介面及相關類在java.sql包和javax.sql包里。我們可以用它來連接資料庫,執行SQL查詢,存儲過程,並處理返回的結果。
JDBC介面讓Java程序和JDBC驅動實現了松耦合,使得切換不同的資料庫變得更加簡單。
JDBC的連接步驟
執行一次JDBC連接,分六個步驟進行:
1. 導入包
在程序中包含資料庫編程所需的JDBC類。大多數情況下,使用 import java.sql.* 就足夠了
2. 注冊JDBC驅動程序
需要初始化驅動程序,這樣就可以打開與資料庫的通信。
3. 打開一個連接
使用DriverManager.getConnection()方法來創建一個Connection對象,它代表一個資料庫的物理連接。
4. 執行一個查詢
需要使用一個類型為Statement或PreparedStatement的對象(兩者區別看後文),並提交一個SQL語句到資料庫執行查詢。
5. 從結果集中提取數據
這一步中演示如何從資料庫中獲取查詢結果的數據。使用ResultSet.getXXX()方法來檢索的數據結果
6. 清理環境資源
在使用JDBC與數據交互操作資料庫中的數據後,應該明確地關閉所有的資料庫資源以減少資源的浪費。本文使用了try with resources方式關閉資源,這是JDK7的語法糖,讀者可自行搜索。
完整代碼如下。
JDBC的最佳實踐
JDBC是如何實現Java程序和JDBC驅動的松耦合?
JDBC API使用Java的反射機制來實現Java程序和JDBC驅動的松耦合。看一下上文的JDBC示例,你會發現所有操作都是通過JDBC介面完成的,而驅動只有在通過Class.forName反射機制來載入的時候才會出現。
這是Java核心庫里反射機制的最佳實踐之一,它使得應用程序和驅動程序之間進行了隔離,讓遷移資料庫的工作變得更簡單。
Statement和PreparedStatement區別
預編譯
創建時的區別:
執行時的區別:
由上可以看出,PreparedStatement有預編譯的過程,已經綁定sql,之後無論執行多少次,都不會再去進行編譯,而Statement 不同,如果執行多次,則相應的就要編譯多少次sql,所以從這點看,PreparedStatement的效率會比Statement要高一些。PreparedStatement是預編譯的,所以可以有效的防止SQL注入等問題
佔位符
PrepareStatement可以替換變數在SQL語句中可以包含?,可以用?替換成變數。
而Statement只能用字元串拼接。
JDBC的ResultSet
在查詢資料庫後會返回一個ResultSet,它就像是查詢結果集的一張數據表。
ResultSet對象維護了一個游標,指向當前的數據行。開始的時候這個游標指向的是第一行。如果調用了ResultSet的next()方法游標會下移一行,如果沒有更多的數據了,next()方法會返回false。可以在for循環中用它來遍歷數據集。
默認的ResultSet是不能更新的,游標也只能往下移。也就是說你只能從第一行到最後一行遍歷一遍。不過也可以創建可以回滾或者可更新的ResultSet,像下面這樣。
當生成ResultSet的Statement對象要關閉或者重新執行或是獲取下一個ResultSet的時候,ResultSet對象也會自動關閉。
可以通過ResultSet的getter方法,傳入列名或者從1開始的序號來獲取列數據。
ResultSet的不同類型
根據創建Statement時輸入參數的不同,會對應不同類型的ResultSet。如果你看下Connection的方法,你會發現createStatement和prepareStatement方法重載了,以支持不同的ResultSet和並發類型。
ResultSet對象有三種類型。
ResultSet有兩種並發類型。
㈡ 在java中如何實現預編譯
/*
* ProCompile.java *預處理要編譯的文件,刪除多餘的空白,注釋,換行,回車等
* Created on 2007年9月18日, 下午8:58 */ package javacompile; import java.io.*;
import java.util.regex.*;
import javax.swing.JOptionPane; /** * @com.junjian.sun public class PerCompile { File f = null;
String fileString = null;
Pattern p = null;
Matcher m = null;
String regex; //正則表達式 //初始化p
public PerCompile() {
regex ="(//.+)" + //(//.+) 對應單行注釋
//"|(/\\*(.+\\n)+\\*/)"+ // 想對應多行注釋... "|(\\r\\n)" + "|(\\n)"+//(\\r\\n)|(\\n)對應換行
"|(\\B\\s+)" ; // 空白符
String ss;
f = new File(new JOptionPane()
.showInputDialog("請輸入文件所在路徑~"));
try {
BufferedReader bf = new BufferedReader(new FileReader(f));
ss = bf.readLine()+"\n";
fileString = ss; //如果沒有這兩句,ss的開頭會有「null」
while((ss = bf.readLine())!= null){
fileString += ss+"\n"; bf.close();
} catch (IOException ex) {
ex.printStackTrace(); p = Pattern.compile(regex);
m = p.matcher(fileString); //執行替換所有多餘空行,空白符,注釋
void Dels(){
System.out.println("before: "+fileString);
if(m.find()) System.out.println("find!!");
System.out.println(m.replaceAll("")); } }
-
㈢ java jdbc 預編譯語句和普通語句的區別
應該指的是Statement和PreparedStatement把。
如果你的查詢語句很少用的話, 用Statement,
如果你的查詢語句常用的話, 就用PreparedStatement。
㈣ java jdbc中Statement,ResultSet,PreparedStatement中各代表什麼意思
區別:
Statement執行一條sql就得編譯一次,PrepareStatement只編譯一次;常用後者原因在於參數設置非常方便;執行一條sql就得編譯一次,後者只編譯一次;還有就是sql放置的位置不同;常用後者原因在於參數設置非常方便;
一般我們使用PreparedStatement代替Statement,因為:
一.代碼的可讀性和可維護性.
雖然用PreparedStatement來代替Statement會使代碼多出幾行,但這樣的代碼無論從可讀性還是可維護性上來說.都比直接用Statement的代碼高很多檔次:
stmt.executeUpdate("insertintotb_name(col1,col2,col2,col4)values('"+var1+"','"+var2+"',"+var3+",'"+var4+"')");
perstmt=con.prepareStatement("insertintotb_name(col1,col2,col2,col4)values(?,?,?,?)");
perstmt.setString(1,var1);
perstmt.setString(2,var2);
perstmt.setString(3,var3);
perstmt.setString(4,var4);
perstmt.executeUpdate();
二.PreparedStatement盡最大可能提高性能.
每一種資料庫都會盡最大努力對預編譯語句提供最大的性能優化.因為預編譯語句有可能被重復調用.所以語句在被DB的編譯器編譯後的執行代碼被緩存下來,那麼 下次調用時只要是相同的預編譯語句就不需要編譯,只要將參數直接傳入編譯過的語句執行代碼中(相當於一個涵數)就會得到執行.這並不是說只有一個 Connection中多次執行的預編譯語句被緩存,而是對於整個DB中,只要預編譯的語句語法和緩存中匹配.那麼在任何時候就可以不需要再次編譯而可以 直接執行.而statement的語句中,即使是相同一操作,而由於每次操作的數據不同所以使整個語句相匹配的機會極小,幾乎不太可能匹配
三.最重要的一點是極大地提高了安全性.
使用預編譯語句.你傳入的任何內容就不會和原來的語句發生任何匹配的關系.只要全使用預編譯語句,你就用不著對傳入的數據做任何過慮.而如果使用普通的statement,有可能要對drop,;等做費盡心機的判斷和過慮.
至於ResultSet,ResultSet 包含符合 SQL 語句中條件的所有行,並且它通過一套 get 方法(這些 get 方法可以訪問當前行中的不同列)提供了對這些行中數據的訪問,例如:
java.sql.Statementstmt=conn.createStatement();
ResultSetr=stmt.executeQuery("SELECTa,b,cFROMTable1");
while(r.next())
{
//列印當前行的值。
inti=r.getInt("a");
Strings=r.getString("b");
floatf=r.getFloat("c");
System.out.println("ROW="+i+""+s+""+f);
}
㈤ jdbc預編譯 如何執行null值
傳過來的值為null,那麼get之後的值也為null,不用關心的吧!
㈥ jdbc預編譯語句的問題
缺少預編譯語句參數int resultSetType , int resultSetConcurrency
可以分別設置為ResultSet.TYPE_SCROLL_INSENSITIVE , ResultSet.CONCUR_READ_ONLY
㈦ java中連接資料庫里的數據源驅動器和jdbc驅動器是一回事嗎,還是說數據源驅動器是運行資料庫,jdbc是連接的
通過JAVA的內置的JDBC訪問資料庫,統稱JDBC方法。驅動就有很多種,基本每一種DB,都有一個驅動,有的還有多種驅動。
下面是Oracle的更新例子
Connection conn=null;
try{
Class.forName("oracle.jdbc.driver.OracleDriver");
String url="jdbc:oracle:thin:@192.168.1.111:1521:XE";
String user="user1", pwd="user1";
conn=DriverManager.getConnection(url, user, pwd);
String sql = "UPDATE family SET income=?,pay=?,time=?,note=? WHERE fnumber=?";
PreparedStatement pstmt1 = conn.prepareStatement(sql);
pstmt1.setString(1, income);
pstmt1.setString(2, pay);
pstmt1.setString(3, time);
pstmt1.setString(4, note);
pstmt1.setString(5, fnumber);
pstmt1.executeUpdate();
return "修改成功";
}catch(Exception e){
e.printStackTrace();
return "修改失敗" ;
}finally{
if(conn!=null){
try{
conn.close();
}catch(Exception e){
}
}
}
㈧ java jdbc中Statement,ResultSet,PreparedStatement中各代表什麼意思
Statement介面:用於執行不帶參數的簡單SQL語句。創建Statement實例對象後可以調用JDBC提供的3種執行SQL語句的方法:(1)executeUpdate()方法,一般用於執行SQL的INSERT,DELETE,UPDATE語句(2)executeQuery()方法,一般用於執行SQL的SELECT語句,因為它的返回值是執行SQL語句後產生的一個ResultSet介面的實例(結果集)(3)execute()方法,即一般它執行的SQL語句既有查詢又有更新值,約等於executeUpdate()和executeQuery()兩個方法的合輯。PreparedStatement介面:它與Statement的主要區別(1)它包含的SQL語句是預編譯的,所以當多次執行一條SQL語句時用它會更快(2)在設置參數是可以用「?」代替。如:PreparedStatementpstmt=conn.preparedStatement(insertintotestvalues(?,?));pstmt.setString(1,'gg');pstmt.setString(2,'123');ResultSet介面:包含了Statement和PreparedStatement的executeQuery方法中SELECT的結果集。相當於用它來讀取資料庫里每列的值。㈨ java jdbc中事務可以預編譯傳參數嗎
1)載入資料庫驅動
通常我們使用Class類的forName()靜態方法來載入驅動(由各個資料庫廠商自己實現)
Class.forName("com.mysql.jdbc.Driver");
Class.forName("oracle.jdbc.driver.OracleDriver");
"com.mysql.jdbc.Driver"、"oracle.jdbc.driver.OracleDriver"代表了資料庫驅動類對應的字元串
2)通過DriverManager獲取資料庫連接
DriverManager.getConnection(Stringurl,Stringuser,Stringpass);
2.1)url:資料庫連接字元串
2.1.1)Mysql
jdbc:mysql://hostname:port/databasename
2.1.2)Oracle
jdbc:oracle:thin:@hostname:port:databasename
2.2)user:資料庫的系統用戶名
2.3)pass:資料庫的系統密碼
3)通過Connection對象創建Statement對象,Connection創建Statement對象的方法有如下3個
3.1)createStatement(Stringsql):創建基本的Statement對象
3.2)prepareStatement(Stringsql):根據傳入的SQL語句創建預編譯的Statement對象
3.3)prepareCall(Stringsql):根據傳入的SQL語句創建CallableStatement對象
4)使用Statement執行SQL語句
所有的Statement都有如下3個方法來執行SQL語句
4.1)execute():可以執行任何SQL語句,但比較麻煩
4.2)executeUpdate():主要用於執行DML和DDL語句。執行DML語句返回受SQL影響的行數,執行DDL語句返回0
4.3)executeQuery():只能執行查詢語句,執行後返回代表查詢結果的ResultSet對象
5)操作結果集
如果執行的SQL語句是查詢語句,則執行結果將返回一個ResultSet對象,該對象里保存了SQL語句查詢的結果。程序可以通過操作該ResultSet對象來取出查詢結果。ResultSet對象主要提供了如
下方法
5.1)移動記錄指針的方法
5.1.1)next()
5.1.2)previous()
5.1.3)first()
5.1.4)last()
5.1.5)beforeFirst()
5.1.6)afterLast()
5.1.7)absolute()
5.2)獲取指針指向的某行的"特定的列值"
5.2.1)getInt()
5.2.2)getString()
...
該方法既可以使用列索引作為參數,也可以使用列名作為參數
6)回收資料庫資源
包括關閉ResultSet、Statement、Connection等資源
