概念糾正:html
如下概念來自官方:
>java
The JDBC API is a Java API for accessing virtually any kind of tabular data. (As a point of interest, JDBC is the trademarked name and is not an acronym; nevertheless, JDBC is often thought of as standing for 「Java Database Connectivity.」) The JDBC API consists of a set of classes and interfaces written in the Java programming language that provide a standard API for tool/database developers and makes it possible to write industrial strength database applications using an all-Java APImysql
JDBC API是一種Java API,用於訪問幾乎任何類型的表格數據。(做爲一個興趣點,JDBC是商標名稱,並非首字母縮略詞;然而,JDBC一般被認爲表明「Java數據庫鏈接」。)JDBC API由一組用Java編寫的類和接口組成。爲工具/數據庫開發人員提供標準API的編程語言,可使用全Java API編寫工業級數據庫應用程序。程序員
The JDBC API makes it easy to send SQL statements to relational database systems and supports all dialects of SQL. But the JDBC 2.0 API goes beyond SQL, also making it possible to interact with other kinds of data sources, such as files containing tabular data.sql
JDBC API能夠輕鬆地將SQL語句發送到關係數據庫系統,並支持全部SQL方言。可是JDBC 2.0 API超越了SQL,也使得與其餘類型的數據源(例如包含表格數據的文件)進行交互成爲可能。數據庫
The value of the JDBC API is that an application can access virtually any data source and run on any platform with a Java Virtual Machine. In other words, with the JDBC API, it isn’t necessary to write one program to access a Sybase database, another program to access an Oracle database, another program to access an IBM DB2 database, and so on. One can write a single program using the JDBC API, and the program will be able to send SQL or other statements to the appropriate data source. And, with an application written in the Java programming language, one doesn’t have to worry about writing different applications to run on different platforms. The combination of the Java platform and the JDBC API lets a programmer write once and run anywhere.編程
JDBC API的價值在於,應用程序幾乎能夠訪問任何數據源,並能夠在任何具備Java虛擬機的平臺上運行。換句話說,使用JDBC API,沒必要編寫一個程序來訪問Sybase數據庫,另外一個程序訪問Oracle數據庫,另外一個程序訪問IBM DB2數據庫,等等。可使用JDBC API編寫單個程序,程序將可以將SQL或其餘語句發送到適當的數據源。並且,使用Java編程語言編寫的應用程序,人們沒必要擔憂編寫不一樣的應用程序以在不一樣的平臺上運行。Java平臺和JDBC API的結合使程序員能夠編寫一次並在任何地方運行。數組
The JDBC API is the industry standard for database-independent connectivity between the Java programming language and a wide range of databases. The JDBC API provides a call-level API for SQL-based database access. JDBC technology allows you to use the Java programming language to exploit 「Write Once, Run Anywhere」 capabilities for applications that require access to enterprise data.安全
JDBC API是Java編程語言與各類數據庫之間數據庫無關鏈接的行業標準。JDBC API爲基於SQL的數據庫訪問提供了調用級API。JDBC技術容許您使用Java編程語言爲須要訪問企業數據的應用程序利用「一次編寫,隨處運行」功能bash
簡單來講,基於JDBC技術的驅動程序(「JDBC驅動程序」)能夠作三件事:
- 創建與數據源的鏈接
- 將查詢和更新語句發送到數據源
- 處理結果
JDBC API主要位於JDK中的java.sql包中(以後擴展的內容位於javax.sql包中),主要包括(斜體表明接口,需驅動程序提供者來具體實現):
- DriverManager:負責加載各類不一樣驅動程序(Driver),並根據不一樣的請求,向調用者返回相應的數據庫鏈接(Connection)。
Driver:驅動程序,會將自身加載到DriverManager中去,並處理相應的請求並返回相應的數據庫鏈接(Connection)。 Connection:數據庫鏈接,負責進行與數據庫間的通信,SQL執行以及事務處理都是在某個特定Connection環境中進行的。能夠產生用以執行SQL的Statement。 Statement:用以執行SQL查詢和更新(針對靜態SQL語句和單次執行)。 PreparedStatement:用以執行包含動態參數的SQL查詢和更新(在服務器端編譯,容許重複執行以提升效率)。 CallableStatement:用以調用數據庫中的存儲過程。- SQLException:表明在數據庫鏈接的建立和關閉和SQL語句的執行過程當中發生了例外狀況(即錯誤)。
從根本上來講,JDBC是一種規範,它提供了一套完整的接口,容許對底層數據庫進行可移植的訪問,Java能夠用於編寫不一樣類型的可執行文件,例如:
- Java Applications
- Java Applets
- Java Servlets
- Java ServerPages(JSps)
- Enterp JavaBeans(EJBs)
這些不一樣的可執行文件都可以使用JDBC驅動程序訪問數據庫,JDBC提供與ODBC相同的功能,容許Java程序包含與數據庫無關的代碼
JDBC API支持用於數據庫訪問的兩層和三層模型。
image在雙層模型中,Java applet或應用程序直接與數據源對話。這須要一個JDBC驅動程序,它能夠與正在訪問的特定數據源進行通訊。用戶的命令被傳遞到數據庫或其餘數據源,而且這些語句的結果被髮送回用戶。數據源能夠位於用戶經過網絡鏈接的另外一臺機器上。這被稱爲客戶端/服務器配置,用戶的機器做爲客戶端,機器將數據源做爲服務器。網絡能夠是內聯網,例如,鏈接公司內的員工,或者能夠是因特網
- 數據庫訪問的三層體系結構
image在三層模型中,命令被髮送到服務的「中間層」,而後將命令發送到數據源。數據源處理命令並將結果發送回中間層,而後中間層將它們發送給用戶。MIS主管發現三層模型很是具備吸引力,由於中間層能夠保持對訪問的控制以及能夠對公司數據進行的更新。另外一個優勢是它簡化了應用程序的部署。最後,在許多狀況下,三層架構能夠提供性能優點。直到最近,中間層一般使用C或C ++等語言編寫,這些語言提供了快速的性能。可是,隨着優化編譯器的引入,將Java字節碼轉換爲高效的機器特定代碼和技術,例如Enterprise JavaBeanstm,Java平臺正迅速成爲中間層開發的標準平臺。這是一個很大的優點,能夠利用Java的健壯性,多線程和安全功能。隨着企業愈來愈多地使用Java編程語言編寫服務器代碼,JDBC API在三層體系結構的中間層中愈來愈多地被使用。使JDBC成爲服務器技術的一些功能是它支持鏈接池,分佈式事務和斷開鏈接的行集。固然,JDBC API容許從Java中間層訪問數據源。
SQL是訪問關係數據庫的標準語言。不幸的是,SQL尚未像人們想的那樣標準化。
一個難點是不一樣DBMS(數據庫管理系統)使用的數據類型有時會有所不一樣,而且變化可能很大。JDBC經過在類中定義一組通用SQL類型標識符來處理此問題java.sql.Types。請注意,在本資料中使用的術語「JDBC SQL類型」,「JDBC類型」和「SQL類型」是可互換的,而且是指在中定義的通用SQL類型標識符java.sql.Types。在「映射SQL和Java類型」一章中有關於數據類型一致性的更完整的討論。
SQL一致性的另外一個難點是儘管大多數DBMS使用標準形式的SQL來實現基本功能,但它們不符合最近定義的標準SQL語法或更高級功能的語義。例如,並不是全部數據庫都支持存儲過程或外部聯接,而且那些數據庫並不老是相互一致。此外,對SQL3功能和數據類型的支持也有很大差別。但願真正標準的SQL部分將擴展爲包含愈來愈多的功能。可是,在此期間,JDBC API必須支持SQL。
JDBC API處理此問題的一種方法是容許將任何查詢字符串傳遞給底層DBMS驅動程序。這意味着應用程序能夠根據須要自由使用盡量多的SQL功能,可是它存在在某些DBMS上收到錯誤的風險。實際上,應用程序查詢可能不是SQL,或者它多是爲特定DBMS設計的SQL的專用衍生物(例如,用於文檔或圖像查詢)。
JDBC處理SQL一致性問題的第二種方法是提供ODBC樣式的轉義子句。轉義語法爲SQL分歧的幾個更常見的領域提供了標準的JDBC語法。例如,日期文字和存儲過程調用都有轉義。
對於複雜的應用程序,JDBC以第三種方式處理SQL一致性。它經過接口提供有關DBMS的描述性信息,DatabaseMetaData以便應用程序能夠適應每一個DBMS的要求和功能。可是,典型的最終用戶無需擔憂元數據。
因爲JDBC API用做開發數據庫訪問工具和其餘API的基本API,所以它還必須解決構建在其上的任何內容的一致性問題。JDBC驅動程序必須至少支持ANSI SQL-92 Entry Level。(ANSI SQL-92指的是1992年美國國家標準協會採用的標準。入門級指的是SQL功能的特定列表。)可是,請注意,儘管JDBC 2.0 API包括對SQL3和SQLJ的支持,但JDBC驅動程序不須要支持他們。
鑑於數據庫供應商,鏈接供應商,Internet服務供應商和應用程序編寫者普遍接受JDBC API,它已成爲Java編程語言數據訪問的標準。
JDBC API提供一下接口和類
- DriverManager: 該類管理數據庫驅動列表.使用通訊自協議匹配來自Java應用程序的鏈接請求和正確的數據庫驅動程序.識別JDBC下某個子協議的第一個驅動程序將用於創建數據庫鏈接.
- Driver: 此接口處理與數據庫服務器的通訊. 您將不多直接與Driver對象進行交互.而是使用DriverManager對象來管理此類對象.它還抽象了與使用Driver對象相關的細節.
- Connection:此接口包含用於聯繫數據庫的全部方法.鏈接對象表示通訊上下文.即,與數據庫的全部通訊僅經過鏈接的對象.
- Statement: 您使用此接口建立的對象將SQL語句提交到數據庫,除執行存儲過程外,某些派生接口還接受參數.
- ResultSet: 在使用Statement對象執行SQL查詢後,這些對象保存從數據庫檢索的數據,它充當迭代器,容許您遍歷其數據.
- SQLException: 此類處理數據庫應用程序中發生的任何錯誤.
JDBC驅動程序實現了在JDBC API中定義的接口,用於於數據庫服務器交互。例如:使用JDBC驅動程序能夠經過發送SQL或數據庫命令,而後使用Java接收結果,讓你打開數據庫鏈接並與數據庫進行交互。JDK附帶的 Java.sql包中包含了各類類,其行爲已定義,其實際實如今第三方驅動程序中完成。第三方供應商在其數據庫驅動程序中實現java.sql.Driver接口。下圖顯示了各類驅動程序實現的可能性:
image在開發JDBC API以前,Microsoft的ODBC(開放數據庫鏈接)API是用於訪問關係數據庫的最普遍使用的編程接口。
JDBC驅動程序實現因Java運行的各類操做系統和硬件平臺而異,Sun將實現類型分爲四種類型:
Type 1:JDBC-ODBC Bridge Driver
該類型驅動程序中,JDBC橋接器用於訪問安裝在每臺客戶機上的ODBC驅動程序。驅動把全部JDBC的調用傳遞給ODBC,再讓後者調用數據庫本地驅動代碼(也就是數據庫廠商提供的數據庫操做二進制代碼庫,例如Oracle中的oci.dll),使用ODBC須要在系統上配置表示目標數據庫的數據源名稱(DSN)
當Java第一次出現時,這是一個有用的驅動程序,由於大多數的數據庫只支持ODBC訪問,但如今推薦這種類型的驅動程序僅用於實驗用途或沒有其餘代替方案可用
image優勢:
- 只要有對應的ODBC驅動(大部分數據庫廠商都會提供),幾乎能夠訪問全部的數據庫。
缺點:
- 執行效率比較低,不適合大數據量訪問的應用
- 因爲須要客戶端預裝對應的ODBC驅動,不適合Internet/Intranet應用
Type 2:JDBC-Native API
在該類型驅動程序中,驅動經過客戶端加載數據庫廠商提供的本地代碼庫(C/C++等)來訪問數據庫,JDBC API調用將轉換爲本機C/C++ API調用,這些調用對於數據庫是惟一的。與JDBC-ODBC Bridge的使用方式相同,必須在每臺客戶端計算機上安裝供應商特定的驅動程序。
若是咱們更改數據庫,咱們必須更改本機API,由於它是特定於數據庫的並且如今幾乎已通過時,可是你可能會經過該類型的驅動程序實現一些速度提高,由於它消除了ODBC的開銷
image優勢:
- 速度快於第一類驅動(但仍比不上第三、第4類驅動)。
缺點:
- 因爲須要客戶端預裝對應的數據庫廠商代碼庫,仍不適合Internet/Intranet應用。
Type 3:JDBC-Net pure Java (網絡協議)
此驅動程序給客戶端提供了一個網絡API,客戶端上的JDBC使用套接字(Socket)來調用服務器上的中間件程序,該程序將JDBC調用轉換爲獨立於DBMS的網絡協議,而後由服務器將其轉換爲DBMS協議並轉發到數據庫服務器。這個網絡服務器中間件可以將其純Java客戶端鏈接到許多不一樣的數據庫。使用的具體協議取決於供應商。一般,這是最靈活的JDBC替代方案,它不須要在客戶端上安裝代碼。該解決方案的全部供應商均可能提供適合Intranet使用的產品。爲了使這些產品也支持Internet訪問,它們必須處理Web強加的安全性,經過防火牆訪問等的附加要求。
image能夠將應用程序服務器視爲JDBC「代理」,這意味着它會調用客戶端應用程序。所以,須要瞭解應用程序服務器的配置,以便有效地使用此驅動程序。
優勢:
- 不須要在客戶端加載數據庫廠商提供的代碼庫,單個驅動程序能夠對多個數據庫進行訪問,可擴展性較好。
缺點:
- 在中間件層仍需對最終數據進行配置
- 因爲多出一箇中間件層,速度不如第四類驅動程序
Type 4:Pure Java
這種類型的驅動程序將JDBC調用直接轉換爲DBMS使用的網絡協議。這容許從客戶端計算機直接調用DBMS服務器,是Intranet訪問的絕佳解決方案。因爲許多協議都是專有的,所以數據庫供應商自己就是主要來源。
在Type 4驅動程序中,基於純Java的驅動程序經過套接字鏈接與供應商的數據庫直接通訊。這是數據庫可用的最高性能驅動程序,一般由供應商本身提供。
這種驅動是很是靈活的,不須要在客戶端或服務器上安裝特殊的軟件。此外,這些驅動程序能夠動態下載。
image優勢:
- 訪問速度最快
- 這是最直接、最純粹的Java實現
缺點:
- 幾乎只有數據庫廠商本身才能提供這種類型的JDBC驅動
- 須要針對不一樣的數據庫使用不一樣的驅動程序
MySql的 Connector/J 就是Type 4驅動程序。因爲其網絡協議的專有性質,數據庫供應商一般提供Type 4驅動程序。
JDBC API包含兩組主要的接口:第一組是應用程序編寫者的JDBC API,第二組是驅動程序編寫者的低級JDBC驅動程序API。應用程序和applet可使用基於純Java JDBC技術的驅動程序經過JDBC API訪問數據庫,如圖所示:
image左側Type 4,右側Type 3下圖說明了使用ODBC驅動程序和現有數據庫客戶端庫的JDBC鏈接:
image左側Type 1,右側Type 2
應該使用哪一種驅動程序?
驅動類別|全Java|網絡鏈接
-|-|-
JDBC-ODBC Bridge|No|Direct
Native API as basis|No|Direct
JDBC-Net|client Yes/server Maybe|Indirect
Native protocol as basis|Yes|Direct
- Direct:JDBC客戶端直接與DBMS服務器創建的鏈接,該服務器多是遠程的
- Indirect:JDBC客戶端與中間件進程創建的鏈接,充當DBMS服務器的橋樑
驅動程序Type 3和4是使用JDBC API訪問數據庫的首選方法。驅動程序Type 1和2是臨時解決方案,其中還沒有提供直接純Java驅動程序。對於須要中間件的Type 1和Type 2(下表中未顯示)可能存在差別,但這些一般是不太理想的解決方案。Type 3和4提供了Java技術的全部優勢
- 若是要訪問某種類型的數據庫(如Oracle,Sybase或IBM),則首選Type 4驅動程序
- 如股票Java應用程序同時訪問多種類型的數據庫,則Type 3是首選驅動程序
- 當Type 3或Type 4驅動程序不可用的狀況下采用Type 2驅動程序
- Type 1驅動程序不被視爲部署及驅動程序,一般僅用於開發和測試
安裝了適當的驅動程序後,就可使用JDBC簡歷數據庫鏈接了.如下是四個基本步驟:
- 導入JDBC包:須要包含數據庫變成所需的JDBC類的包.大多數狀況下,
使用import sql.*就夠了- 註冊JDBC驅動程序:須要初始化驅動程序,將JVM所需的驅動程序實現加載到內存中,以即可以打開與數據庫的通訊通道.
- 打開一個鏈接: 須要使用DriverManager.getConneection()方法建立一個Conection對象,它表示與數據庫的物理鏈接.
- 執行查詢:須要使用類型爲Statement的對象來構建和提交SQL語句到數據庫.
- 從結果集中提取數據:須要使用相應的ResultSet.getXXX()方法從結果集中檢索數據.
- 清理環境: 須要明確的關閉全部數據庫資源,而不依賴於JVM的垃圾回收.
import語句告訴Java編輯器在哪裏找到你在代碼中引用的類的源代碼位置.要使用標準JDBC包(容許在SQL表中選擇,插入,更新和刪除數據),請將如下導入添加到源代碼中:
impor java.sql.*;
複製代碼
在實用程序以前,必須先註冊該驅動程序,將驅動程序的類文件加載到內存中,所以能夠將其用做JDBC接口的實現。
Class.forName();
註冊驅動程序最經常使用的方法是使用Java的Class.forName()將驅動程序的類文件動態加載到內存中,自動註冊他。此方法是首選,由於它使驅動程序的註冊可配置和可移植。
try{
Class.forName("com.mysql.jdbc.Driver");
}catch(ClassNotFoundException e){
//
}
複製代碼
註冊驅動實際執行下面代碼:
static {
try {
java.sql.DriverManager.registerDriver(new Driver());
} catch (SQLException E) {
throw new RuntimeException("Can't register driver!");
}
}
複製代碼
可使用DriverManager.getConnection() 方法創建鏈接。爲了便於參考,這裏列出三個重載的方法:
- getConnection(String url)
- getConnection(String url,Properties prop)
- getConnection(String url,String user,String password)
每一個方法都須要一個數據庫URL,下表列出了經常使用的JDBC、驅動程序名稱和數據庫URL。
RDBMS|JDBC驅動程序名稱|網址格式
-|-|-
MySQL|com.mysql.jdbc.Driver|jdbc:myql://hostname/databaseName
ORACLE|oracle.jdbc.driver.OracleDriver|jdbc:oracle:thin:@hostname:port:databaseName
DB2|com.ibm.db2.jdbc.net.DB2Driver|jdbc:db2: hostname:port/databaseName
Sysbase|com.sybase.jdbc.SybDriver|jdbc:sybase:Tds: hostname:port/databaseName
URl中突出顯示的部分都是靜態的,只須要根據數據庫設置更改剩餘部分。
數據庫服務安裝在本機,端口號爲3306,用戶名爲root,密碼爲root,數據庫名是test。
String url = "jdbc:mysql://localhost:3306/test";
String user = "root";
String password = "root";
Connection connection = DriverManager.getConnection(url,user,password);
複製代碼
String url = "jdbc:mysql://localhost:3306/test?user=root&password=root";
Connection connection = DriverManager.getConnection(url);
複製代碼
String url = "jdbc:mysql://localhost:3306/test";
Properties info = new Properties();
info.put("user","root");
info.put("password","root");
Connection connection = DriverManager.getConnection(url,info);
複製代碼
在JDBC程序結束時,須要明確關閉全部的數據庫鏈接。若是在程序中忘了關閉,Java垃圾回收器將在清理果實對象時關閉該鏈接。
可是依靠垃圾回收,特別是數據庫編程,是一個很很差的編程實踐。因此應該要養成使用與鏈接對象關聯的close()方法關閉鏈接的習慣。
要確保鏈接已關閉,能夠將關閉鏈接的代碼編寫在「finally」塊中,無論是否發生異常「finally」塊最後老是會執行。
connection.close();
複製代碼
一旦得到連接,咱們就能夠與數據庫進行交互。JDBC Statement,PreparedStatement和CallableStatement接口定義了可以發送SQL或PL/SQL命令以及從數據庫接收數據的方法和屬性。
他們還定義了有助於橋接數據庫中使用的Java和SQL數據類型之間的數據類型差別的方法。
下表提供了每一個接口肯定要使用的接口的目的的摘要。
接口|推薦用途
-|-
Statement|用於對數據庫的通用訪問。在運行時使用靜態SQL語句時頗有用。Statement接口不能接收參數。
PreparedStatement|當你計劃屢次使用SQL語句時使用。PreparedStatement接口在運行時能夠接收輸入參數。
CallableStatement|在想要訪問數據庫存儲過程時使用。CallableStatement接口也能夠接受運行時輸入的參數。
Statement stmt = null;
try{
stmt = connection.createStatement();
}catch(SQLException e){
...
}finally{
stmt.close();
}
複製代碼
在建立Statement對象後,可使用它來執行一個SQL語句,它有三個方法能夠執行。分別是:
- boolean execute(String sql):若是能夠檢索到ResultSet對象,則返回一個布爾值true,不然返回false。使用此方法執行SQL DDL語句或者須要使用真正的動態SQL,可使用執行建立數據庫,建立表的SQL語句等等。
- int executeUpdate(String sql):返回受執行SQL語句所影響的行數。使用次方法執行預期會影響多行的SQL語句,例如:INSERT、UPDATE或DELETE語句。
- ResultSet executeQuery(String sql):返回一個ResultSet對象。當您西往得到結果集時,請使用此方法,就像使用SELECT語句同樣。
關閉Statement對象
就像關閉Connection對象以保存數據庫資源同樣,出於一樣的緣由,也應該關閉Statement對象。若是先關閉Connection對象,它也會關閉Statement對象。可是應該明確關閉Statement對象以確保正確的清理順序。
- PreparedStatement對象
PreparedStatement擴展了Statement接口,它提供了一些通用Statement額外的功能。這個語句具備動態提供參數的靈活性。
PreparedStatement pstmt = null;
try{
String sql = "UPDATE Employees SET age = ? WHERE id = ?";
pstmt = connection.prepareStatement(sql);
pstmt.setInt(1,18);
...
}catch(SQLException e){
...
}finally{
pstmt.close();
}
複製代碼
- JDBC中的全部參數都有‘?’符號做爲佔位符,這被稱爲參數標記。在執行SQL語句以前,必須爲每一個參數(佔位符)提供值。
setXXX(int parameterIndex, XXX x) 方法將值綁定到參數,其中XXX表示綁定到輸入參數的值的Java數據類型。若是忘記提供值,將拋出一個SQLException。- 每一個參數標記是它其位置序號的引用。第一個標記表示位置1,下一個位置2等等。該方法與Java數組下標不一樣(從0開始)
- 全部Statement對象與數據庫交互的方法:execute(),executeQuery()和executeUpdate()也能夠用於PreparedStatement對象。可是,這些方法被修改成可使用輸入參數的SQL語句。
關閉PreparedStatement對象
若是先關閉Connection對象,也會關閉PreparedStatement對象。可是,應該明確的關閉PreparedStatement對象以確保正確順序清理資源。
- CallableStatement對象
相似Connection對象建立Statement和PreparedStatement對象同樣,它還可使用桐言的方式建立CallableStatement對象,該對象將用於執行對數據庫存儲過程的調用。
假如須要執行如下MySQL存儲過程:
DELIMITER $$
DROP PROCEDURE IF EXISTS 'EMP'.'getName' $$
CREATE PROCEDURE 'EMP'.'getName'
(IN EMP_ID INT,OUT EMP_FIRST VARCHAR(255)
BEGIN
SELECT first INTO EMP_FIRST
FROM Employees
WHERE ID = EMP_ID;
END $$
DELIMITER ;
複製代碼
存在三種類型的參數:IN,OUT和INOUT。PreparedStatement對象僅使用IN參數。CallableStatement對象可使用這三個。
如下是上面三種類型參數的定義:
參數|描述
-|-
IN|建立SQL語句是其參數值是未知的。使用setXXX()方法將值綁定到IN參數。
OUT|有SQL語句返回的參數值。可使用getXXX()方法從OUT參數中檢索值。
INOUT|提供輸入和輸出值的參數。使用setXXX()方法綁定變量並使用getXXX()方法檢索值。
CallableStatement cstmt = null;
try{
String sql = "{call getEmpName (?,?)}";
cstmt = connection.prepareCall(sql);
...
}catch(SQLException e){
...
}finally{
cstmt.close();
}
複製代碼
String變量sql表示存儲過程,帶有兩個參數佔位符。
使用CallableStatement對象就像使用PreparedStatement對象同樣。在執行語句以前,必須將值綁定到全部參數。不然將拋出一個SQLException。
若是有IN參數,只需遵循適用於PreparedStatement對象的相同規則和技術。
使用OUt和INOUT參數時,必須使用一個額外的CallableStatement對象方法registerOutParameter()。registerOutParamter()方法將JDBC數據類型綁定到存儲過程並返回預期數據類型。
當調用存儲過程,可使用適當的getXXX()方法從OUT參數中檢索該值,此方法將檢索到的SQL類型的值轉換爲對應的Java數據類型。
就像關閉其餘Statement對象同樣,因爲一樣的緣由(節省數據庫系統資源),還應該關閉CallableStatement對象。
簡單的調用close()方法將執行關閉CallableStatement對象。 若是先關閉Connection對象,它也會關閉CallableStatement對象。 可是,應該始終顯式關閉CallableStatement對象,以確保按正確順序的清理資源。
SQL語句執行後從數據庫,返回的數據放在結果集中。SELECT語句用於從數據庫中選擇行並在結果集中查看它們的標準方法。java.sql.ResultSet接口表示數據庫查詢的結果集。
ResultSet接口的方法能夠分爲三類:
- 導航方法:用於移動遊標。
- 獲取方法:用於查看遊標指向的當前行的列中的數據
- 更新方法:用於更新當前行的列中的數據。而後,也能夠在底層數據庫中更新。
遊標可根據ResultSet的屬性移動。在建立生成ResultSet的對應Statement時,將指定這些屬性。
JDBC提供如下連接方法來建立具備所需ResultSet的語句:
- createStatement(int resultSetType,int resultSetConcurrency)
- prepareStatement(String sql,int resultSetType,int resultSetConcurrency)
- prepareCall(String sql,int resultSetType,int resultSetConcurrency)
resultSetType參數表示ResultSet對象的類型,resultSetConcurrency參數指定結果集是隻讀仍是可更新。
Type of ResultSet
能夠指定的的resultSetType類型以下:(若是不指定任何resultSetType類型,將自動分配一個TYPE_FORWARD_ONLY值)
類型|描述
-|-
ResultSet.TYPE_FORWARD_ONLY|遊標只能在結果集中向前移動
ResultSet.TYPE_SCROLL_INSENSITIVE|遊標能夠向前和向後滾動,結果集對建立結果集後發生的數據庫所作的更改不敏感
ResultSet.TYPE_SCROLL_SENSITIVE|遊標能夠向前和向後滾動,結果集對建立結果集以後的其餘數據庫的更改敏感
Concurrency of ResultSet
能夠制定的resultSetConcurrency類型以下:(若是不指定任何resultSetConcurrency類型,將自動分配一個CONCUR_READ_ONLY值)
併發性|描述
-|-
ResultSet.CONCUR_READ_ONLY|建立只讀結果集,這是默認值。
瀏覽結果集
方法|描述
-|-
public void beforeFirst() throw SQLException|將遊標移動到第一行以前
public void afterLast() throw SQLException|將遊標移動到最後一行以後
public boolean first() throw SQLException|將遊標移動到第一行
public void last() throw SQLException|將遊標移動到最後一行
public boolean absolute (int row) throw SQLException|將遊標移動到指定行
public boolean relative (int row) throw SQLException|將遊標從當前位置向前或向後移動給定的行數
public boolean previous () throw SQLException|將遊標移動到上一行
public boolean next() throw SQLException|將遊標移動到下一行
public int getRow() throw SQLException|返回遊標指向的行號
public void moveToInsertRow () throw SQLException|將遊標移動到結果集中的一個特殊行,該行可用於將新航插入數據庫
查看結果集
每一個可能的數據類型都有get方法,每一個get方法都有兩個版本:
- 採用列名稱
- 採用列索引
方法|描述
-|-
public xxx getXXX(String columnName) throws SQLException|返回當前行名爲columnName的列中值
更新結果集
ResultSet接口包含一組用於更新結果集的數據的更新方法。與get方法同樣,每種類型都有兩種:
- 採用列名稱
- 採用列索引
例如,要更新結果集當前行的String例:
方法|描述
-|-
public void updateString(int columnIndex,String s) throw SQLException|將指定列中的String值更改成s的值
public void updateString(String columnName,String s) throw SQLException|將列名爲columnName的String值更改成s的值
更新結果集中的行會更改ResultSet對象中當前行的列,但不會更改基礎數據庫中的列。要想對數據庫中的行進行更改,須要調用如下方法:
方法|描述
-|-
public void updateRow()|經過更新數據庫中相對應行來更新當前行
public void deleteRow()|從數據庫中刪除當前行
public void refreshRow()|刷新結果集中的數據以反映數據庫中的任何最新更改
public void cancelRowUpdates()|取消對當前行進行的任何更新
JDBC驅動程序將Java數據類型轉換爲適當的JDBC類型。而後將其發送到數據庫。它爲大多數數據類型提供並使用默認映射。例如:Java int類型會被轉換成SQL INTERGER。建立默認映射以提供驅動程序之間的一致性
下表總結了在嗲用PreparedStatement或CallableStatement對象的setXXX()方法或ResultSet.updateXXX()方法時,Java數據類型轉換爲JDBC的默認數據類型:
SQL類型|JDBC/Java類型|setXXX|updateXXX
-|-|-|-
VARCHAR|java.lang.String|setString|updateString
CHAR|java.lang.String|setString|updateString
LONGVARCHAR|java.lang.String|setString|updateString
BIT|boolean|setBoolean|updateBoolean
NUMERIC|java.math.BigDecimal|setBigDecimal|updateBigDecimal
TINYINT|byte|setByte|updateByte
SMALLINT|short|setShort|updateShort
INTEGER|int|setInt|updateInt
BIGINT|long|setLong|updateLong
REAL|float|setFloat|updateFloat
FLOAT|float|setFloat|updateFloat
DOUBLE|double|setDouble|updateDouble
VARBINARY|byte[ ]|setBytes|updateBytes
BINARY|byte[ ]|setBytes|updateBytes
DATE|java.sql.Date|setDate|updateDate
TIME|java.sql.Time|setTime|updateTime
TIMESTAMP|java.sql.Timestamp|setTimestamp|updateTimestamp
CLOB|java.sql.Clob|setClob|updateClob
BLOB|java.sql.Blob|setBlob|updateBlob
ARRAY|java.sql.Array|setARRAY|updateARRAY
REF|java.sql.Ref|setRef|updateRef
STRUCT|java.sql.Struct|setStruct|updateStruct
ResultSet對象爲每一個數據類型提供了相應的get方法來檢索列值。每一個方法均可以使用列明或其序號位置來檢索值。
SQL|JDBC/Java|getXXX
-|-|-
VARCHAR|java.lang.String|getString
CHAR|java.lang.String|getString
LONGVARCHAR|java.lang.String|getString
BIT|boolean|getBoolean
NUMERIC|java.math.BigDecimal|getBigDecimal
TINYINT|byte|getByte
SMALLINT|short|getShort
INTEGER|int|getInt
BIGINT|long|getLong
REAL|float|getFloat
FLOAT|float|getFloat
DOUBLE|double|getDouble
VARBINARY|byte[ ]|getBytes
BINARY|byte[ ]|getBytes
DATE|java.sql.Date|getDate
TIME|java.sql.Time|getTime
TIMESTAMP|java.sql.Timestamp|getTimestamp
CLOB|java.sql.Clob|getClob
BLOB|java.sql.Blob|getBlob
ARRAY|java.sql.Array|getARRAY
REF|java.sql.Ref|getRef
若是JDBC鏈接處於自動提交模式(默認狀況下),那麼每一個SQL語句在完成後都會提交到數據庫
對於簡單的應用程序可能沒問題,可是有三個緣由須要考慮是否關閉自動提交併管理本身的事務:
- 提升性能
- 保證業務流程的完整性
- 使用分佈式事務
事務可以控制什麼時候將更改提交併應用於數據庫。它將單個SQL語句或一組SQL語句視爲一個邏輯單元,若是任何語句失敗,則整個事務失敗
要啓動手動事務支持,需調用Connection對象的setAutoCommit()方法。若是將布爾值false傳給setAutoCommit(),則關閉自動提交,也能夠傳遞一個true來從新打開它
connection.setAutoCommit(false);
複製代碼
提交和回滾
完成更改後,若要提交更改,那麼可調用connection對象的commit()方法
connection.commit();
複製代碼
若是要回滾數據庫更新,使用如下代碼:
connection.rollback();
複製代碼
如下示例展現了若是使用提交和回滾:
try{
connection.setAutoCommit(false);
Statement stmt = connection.createStatement();
String sql = "INSERT INTO Employees VALUES (123,'java'); stmt.executeUpdate(sql); connection.commit(); }catch(SQLException e){ connection.rollback(); }finally{ //release resource } 複製代碼
Savepoint
新的JDBC 3.0添加了Savepoint接口提供了額外的事務控制能力。大多數現代DBMS支持其環境中的保存點,
設置Savepoint時,能夠在事務中定義邏輯回滾點。若是在Savepoint以後發生錯誤,則可使用回滾方法來撤銷全部更改或僅保存保存點以後所作的更改。
Connection對象由兩個新方法管理保存點:
- Savepoint setSavepoint(String name):定義新的保存點並返回該對象
- void releaseSavepoint(Savepoint savepoint):刪除保存點。
有一個void rollback(Savepoint savepoint)方法,它將使用事務回滾到制定的保存點。
Savepoint savepoint = null;
try{
connection.setAutoCommit(false);
Statement stmt = connection.createStatement();
String sql = "INSERT INTO Employees VALUES (123,'Java')";
stmt.executeUpdate(sql);
savepoint = connection.setSavepoint("Savepoint");
sql = "INSERT INTO Employees VALUES (456,'C++')";
stmt.executeUpdate(sql);
sql = "INSERT INTO Employees VALUES ('789','Python')";//error sql
stmt.executeUpdate(sql);
connection.commit();
}catch(SQLException e){
if (savepoint == null){
connection.rollback();
}else{
connection.rollback(savepoint);
connection.commit();
}
}finally{
//release resource
}
複製代碼
在這種狀況下,第二條INSERT不會成功。
批量處理容許將相關的SQL語句分組到批處理中,並經過對數據路的一次調用來提交它們。一次向數據庫發送多個SQL語句,能夠減小通訊開銷,從而提升性能
- 應使用DatabaseMetaData的supportsBatchUpdates()方法來肯定目標數據庫是否支持批量更新。若是JDBC驅動程序支持此功能,該方法將返回true
- Statement、PreparedStatement和CallableStatement的addBatch()方法用於將單個語句添加到批處理。
- executeBatch()用於執行分在一組的全部語句並返回一個int數組,數組的每一個元素表示相應的更新語句的更新計數
- clearBatch()方法能夠刪除使用addBatch()方法添加的全部語句。可是沒法選擇要刪除某個語句
- 使用connection.createStatement()方法建立Statement對象
- 使用connection.setAutoCommit(false)取消自動提交
- 使用statement.addBatch(String sql)方法將SQL語句添加到批處理中
- 使用statement.executeBatch()方法執行全部SQL語句
- 使用connection.commit()方法提交全部更改
//create Statement object
Statement stmt = connection.createStatement();
//set auto-commit to false
connection.setAutoCommit(false);
//create some SQL statement
String sql1 = "INSERT INTO Employees VALUES (123,'Java')";
String sql2 = "INSERT INTO Employees VALUES (456,'C++')";
//add above SQL statement in the batch
stmt.addBatch(sql1);
stmt.addBatch(sql2);
//execute batch tasks
int[] result = stmt.executeBatch();
//commit transaction
connection.commit();
複製代碼
使用PreparedStatement對象進行批處理
- 建立帶有佔位符的SQL語句
- 使用connection.prepareStatement()方法建立PreparedStatement對象
- 使用connection.setAutoCommit(false)方法取消自動提交
- 使用preparedStatement.addBatch(String sql)方法將SQL語句添加到批處理中
- 使用preparedStatement.executeBatch()方法執行全部SQL語句
- 使用connection.commit()方法提交全部更改
//create SQL Statement
String sql = "INSERT INTO Employees VALUES (?,?)";
//create PreparedStatement object
PreparedStatement pstmt = connection.prepareStatement(sql);
//set auto-commit to false
connection.setAutoCommit(false);
//set the variables
pstmt.setInt(123);
pstmt.setString("Java");
pstmt.addBatch();
//set the variables
pstmt.setInt(456);
pstmt.setString("C++");
pstmt.addBatch();
//execute batch tasks
int[] result = pstmt.executeBatch();
//commit transaction
connection.commit();
複製代碼
Getting Started with the JDBC API:https://docs.oracle.com/javase/1.5.0/docs/guide/jdbc/getstart/GettingStartedTOC.fm.html
JDBC Tutorial:https://www.tutorialspoint.com/jdbc/index.htm