首先要建立一個(gè)到想要使用的DBMS的連接。這包括兩個(gè)步驟:(1) 加載驅(qū)動(dòng)程序;(2) 創(chuàng)建連接。
(1) 加載驅(qū)動(dòng)程序
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver"); //字符串為他驅(qū)動(dòng)程序的類(lèi)名
(2) 創(chuàng)建連接
創(chuàng)建連接的第二步是使用合適的驅(qū)動(dòng)程序連接到DBMS。如下代碼行示范了一般的用法:
//url字符串為使用的子協(xié)議,也就是在JDBC URL中放在jdbc:之后的東西
Connection con = DriverManager.getConnection(url,"myLogin", "myPassword");
2、創(chuàng)建和執(zhí)行JDBC語(yǔ)句
Statement對(duì)象可將SQL語(yǔ)句發(fā)送到DBMS。這只要?jiǎng)?chuàng)建一個(gè)Statement對(duì)象,將想要執(zhí)行的SQL語(yǔ)句傳遞給適當(dāng)?shù)膱?zhí)行方法,
然后執(zhí)行該Statement對(duì)象。
Statement stmt = con.createStatement();
對(duì)于SELECT語(yǔ)句,使用的方法是executeQuery。對(duì)于創(chuàng)建或修改表的語(yǔ)句,使用的方法是executeUpdate。
//strSQL字符串是一條DDL(數(shù)據(jù)描述語(yǔ)言)語(yǔ)句
stmt.executeUpdate(strSQL);
3、處理結(jié)果
JDBC將結(jié)果集返回給ResultSet對(duì)象
//strSQL字符串是一條查詢(xún)語(yǔ)句
ResultSet rs = stmt.executeQuery(strSQL);1)next方法變量rs(ResultSet的一個(gè)實(shí)例)包含了結(jié)果集中顯示的表。為訪問(wèn)名稱(chēng)和單價(jià)要移動(dòng)到每一行,根據(jù)它們的類(lèi)型檢索數(shù)值。next方法將光標(biāo)移到下一行,使那行(稱(chēng)為當(dāng)前行)成為可在其上操作的行。由于光標(biāo)初始定位于ResultSet對(duì)象第一行的上面,所以第一次調(diào)用next方法將光標(biāo)移到第一行,使它成為當(dāng)前行。接下來(lái)調(diào)用next方法將使光標(biāo)從上至下每次移動(dòng)一行。2)getXXX方法適當(dāng)類(lèi)型的getXXX方法可用于檢索列中的數(shù)值。檢索VARCHAR SQL類(lèi)型數(shù)值的方法是getString。檢索該類(lèi)型數(shù)值的方法是getFloat。每次調(diào)用next方法,下一行就成為當(dāng)前行,循環(huán)一直持續(xù)到rs中再也沒(méi)有可向前移動(dòng)的行為止。while (rs.next()){String s = rs.getString(strColumnName1 );//strColumnName1為strSQL字符串中的列名float n = rs.getFloat(strColumnName2)//strColumnName2為strSQL字符串中的列名System.out.println(s + " " + n);}JDBC使用兩種方法標(biāo)識(shí)getXXX方法檢索數(shù)值的列。一種是指定列名,這也是前面例子所做的。另一種是指定列索引(列的序號(hào)),1表示第一列,2表示第二列,以此類(lèi)推。String s = rs.getString(1); float n = rs.getFloat(2);3)getString方法盡管推薦使用getString方法檢索CHAR和VARCHAR SQL類(lèi)型的數(shù)據(jù),但也可能用它檢索其他基本SQL類(lèi)型的數(shù)據(jù)(但不可用它檢索新的SQL3數(shù)據(jù)類(lèi)型。本教程后面將討論SQL3類(lèi)型)。用getString檢索所有數(shù)值有很多優(yōu)點(diǎn)但也有局限。如果用它檢索numeric類(lèi)型的數(shù)據(jù),getString將把numeric值轉(zhuǎn)換成Java的String對(duì)象,這樣一來(lái),在數(shù)據(jù)要作為數(shù)字前就必須轉(zhuǎn)換回numeric類(lèi)型。在數(shù)值一直當(dāng)成字符串的場(chǎng)合,這是無(wú)可非議的。如果想讓程序檢索除了SQL3類(lèi)型之外的任何標(biāo)準(zhǔn)SQL類(lèi)型,就可用getString方法。4、關(guān)閉連接connection.close();++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++下面是個(gè)完整的例子:1)下載并安裝Microsoft JDBC (http://download.microsoft.com/download/SQLSVR2000/Install/2.2.0022/NT5XP/EN-US/setup.exe)2) 安裝完成Microsoft JDBC后,將安裝目錄中的lib目錄下三個(gè)jar文件msbase.jar, mssqlserver.jar, msutil.jar引入項(xiàng)目中3)建立數(shù)據(jù)庫(kù)tempdb,建立表COFFEES,SQL語(yǔ)句為:CREATE TABLE COFFEES (COF_NAME VARCHAR(32), SUP_ID INTEGER, PRICE FLOAT, SALES INTEGER, TOTAL INTEGER)4)給表COFFEES添加一些數(shù)據(jù),如:INSERT INTO COFFEES VALUES ('Colombian', 101, 7.99, 0, 0);5)輸入以下源文件,并執(zhí)行import java.sql.*;/**
* @author liujun TODO To change the template for this generated type comment go
* to Window - Preferences - Java - Code Style - Code Templates
*/
public class JDBC_01
{public static void main(String[] args)
{
showTable();
}public static void showTable()
{//String strDriver="sun.jdbc.odbc.JdbcOdbcDriver";
String strDriver = "com.microsoft.jdbc.sqlserver.SQLServerDriver";
//String strConnUrl="jdbc:odbc:TempDataSources";
String strConnUrl = "jdbc:microsoft:sqlserver://localhost:1433;DatabaseName=tempdb";
String strSQL = "select * from COFFEES";try
{
//加載驅(qū)動(dòng)程序
Class.forName(strDriver);
//創(chuàng)建連接
Connection objConn = DriverManager.getConnection(strConnUrl, "sa",
"");
//創(chuàng)建Statement對(duì)象
Statement objStatement = objConn.createStatement();
//JDBC將結(jié)果集返回給ResultSet對(duì)象
ResultSet objSet = objStatement.executeQuery(strSQL);
//獲得查詢(xún)結(jié)果的列數(shù)
int lCloumnCount = objSet.getMetaData().getColumnCount();
System.out.println("查詢(xún)結(jié)果如下所示");
//顯示列名
for (int i = 1; i <= lCloumnCount; i++)
{
System.out.print(objSet.getMetaData().getColumnName(i)
+ " ");
}
System.out.println();
//顯示結(jié)果
while (objSet.next())
{
//顯示COF_NAME
System.out.print("" + objSet.getString(1));
//顯示SUP_ID PRICE SALES TOTAL
System.out.print(" " + objSet.getInt(2));
//顯示 PRICE
System.out.print(" " + objSet.getFloat(3));
//顯示SALES
System.out.print(" " + objSet.getInt(4));
//顯示 TOTAL
System.out.print(" " + objSet.getInt(5));}objConn.close();}
catch (Exception e)
{
System.out.print(e.getMessage());
}
}}5、使用預(yù)備語(yǔ)句
PreparedStatement對(duì)象是包含一條預(yù)編譯過(guò)的SQL語(yǔ)句。DBMS不必編譯就可直接運(yùn)行PreparedStatement的SQL語(yǔ)句。所以代替Statement對(duì)象一般會(huì)縮短執(zhí)行時(shí)間。盡管paredStatement對(duì)象可用于不帶參數(shù)的SQL語(yǔ)句,但在多數(shù)場(chǎng)合是用于帶參數(shù)的SQL語(yǔ)句。其用法如下:
String strUpdateSales="UPDATE COFFEES SET SALES = ? WHERE COF_NAME LIKE ?";
PreparedStatement updateSales = con.prepareStatement(strUpdateSales);updateSales.setInt(1, 75);//給上面的SQL語(yǔ)句的第一個(gè)問(wèn)號(hào)付值updateSales.setString(2, "Colombian");//給上面的SQL語(yǔ)句的第二個(gè)問(wèn)號(hào)付值updateSales.executeUpdate();//執(zhí)行UPDATE COFFEES SET SALES = 75 WHERE COF_NAME LIKE ‘Colombian’因此,可用該對(duì)象制作成模板實(shí)現(xiàn)一次構(gòu)造多條帶參數(shù)的SQL語(yǔ)句,簡(jiǎn)化編碼。6、executeUpdate方法的返回值executeQuery返回一個(gè)ResultSet對(duì)象,但executeUpdate返回的是一個(gè)整數(shù)值,指出了表中已更新的行數(shù)如果executeUpdate的返回值為0表明如下兩種情況:(1) 執(zhí)行的語(yǔ)句是一不影響任何行的更新語(yǔ)句;(2) 執(zhí)行的是一DLL語(yǔ)句。7、使用事務(wù)一個(gè)事務(wù)是作為一個(gè)單元執(zhí)行的一組語(yǔ)句(一條或多條語(yǔ)句),因此它們要么全部執(zhí)行,要么全部不執(zhí)行。要讓兩條或更多條語(yǔ)句組成一個(gè)事務(wù)就要禁用自動(dòng)提交模式,具體用方法con.setAutoCommit(false);一旦禁用了自動(dòng)提交模式,就沒(méi)有SQL語(yǔ)句會(huì)提交了,除非您顯式調(diào)用con.commit()方法,實(shí)現(xiàn)提交事務(wù)。使用事務(wù)可以保持?jǐn)?shù)據(jù)完整性。調(diào)用rollback方法可取消一個(gè)事務(wù),將修改的任何數(shù)據(jù)返還到以前的值。如果在執(zhí)行一個(gè)事務(wù)中的一條或多條語(yǔ)句時(shí)得到了SQLException。就應(yīng)該調(diào)用rollback方法取消事務(wù),從頭開(kāi)始整個(gè)事務(wù)。一般要在catch塊中調(diào)用rollback,以避免可能使用不正確的數(shù)據(jù)。8、檢索警告SQLWarning對(duì)象是SQLException的子類(lèi),用于處理數(shù)據(jù)庫(kù)訪問(wèn)警告。就像異常一樣,警告并不終止程序的執(zhí)行;它們只是提醒用戶——發(fā)生了一些未預(yù)料的事情。Connection對(duì)象、Statement對(duì)象(包括PreparedStatement和CallableStatement對(duì)象)或ResultSet對(duì)象都會(huì)報(bào)告警告。這些類(lèi)都有g(shù)etWarnings方法,為查看調(diào)用對(duì)象報(bào)告的第一個(gè)警告,就必須調(diào)用該方法。如果getWarnings返回一個(gè)警告,就可在其上調(diào)用SQLWarning方法getNextWarning取得其他警告。自動(dòng)執(zhí)行一條語(yǔ)句會(huì)清除前一條語(yǔ)句的警告,因此警告不會(huì)迭加。但這也表明提取一條語(yǔ)句報(bào)告的警告必須在執(zhí)行下一語(yǔ)句之前進(jìn)行。9、存儲(chǔ)過(guò)程存儲(chǔ)過(guò)程是一組SQL語(yǔ)句組成的邏輯單元,用于執(zhí)行特定的任務(wù)。存儲(chǔ)過(guò)程用于封裝數(shù)據(jù)庫(kù)服務(wù)器上執(zhí)行的一組操作或查詢(xún)。存儲(chǔ)過(guò)程可以編譯,然后使用不同的參數(shù)和結(jié)果執(zhí)行,這些參數(shù)和結(jié)果可以是輸入、輸出和輸入/輸出參數(shù)的任意組合。1)用SQL語(yǔ)句創(chuàng)建存儲(chǔ)過(guò)程如下所示,其方法同其他的DDL語(yǔ)句相同:String createProcedure = "create procedure SHOW_SUPPLIERS " +"as " +"select SUPPLIERS.SUP_NAME, COFFEES.COF_NAME " +"from SUPPLIERS, COFFEES " +"where SUPPLIERS.SUP_ID = COFFEES.SUP_ID " +"order by SUP_NAME";Statement stmt = con.createStatement();stmt.executeUpdate(createProcedure);2)從JDBC調(diào)用存儲(chǔ)過(guò)程第一步是創(chuàng)建一個(gè)CallableStatement對(duì)象。CallableStatement對(duì)象包含了存儲(chǔ)過(guò)程的一個(gè)調(diào)用;但它不包含存儲(chǔ)過(guò)程本身。接著使用連接con創(chuàng)建了存儲(chǔ)過(guò)程的一個(gè)調(diào)用。花括號(hào)內(nèi)的那部分就是存儲(chǔ)過(guò)程的轉(zhuǎn)義語(yǔ)法。當(dāng)驅(qū)動(dòng)程序碰到“{call SHOW_SUPPLIERS}”時(shí),它將把這個(gè)轉(zhuǎn)義語(yǔ)法轉(zhuǎn)換成數(shù)據(jù)庫(kù)使用的本地SQL,以調(diào)用call 后面的的存儲(chǔ)過(guò)程。如下所示:CallableStatement cs = con.prepareCall("{call SHOW_SUPPLIERS}");ResultSet rs = cs.executeQuery();注意,用于執(zhí)行cs的方法是executeQuery,因?yàn)閏s調(diào)用的存儲(chǔ)過(guò)程包含一個(gè)查詢(xún),執(zhí)行后產(chǎn)生一個(gè)結(jié)果集。如果存儲(chǔ)過(guò)程包含一條更新或一條DLL語(yǔ)句,那就要使用executeUpdate方法。但有時(shí)一個(gè)存儲(chǔ)過(guò)程包含多條SQL語(yǔ)句,因而它產(chǎn)生的不只是一個(gè)結(jié)果集、不只是一個(gè)更新計(jì)數(shù)或產(chǎn)生一些結(jié)果集和更新計(jì)數(shù)的組合。這樣就有多個(gè)結(jié)果集,這時(shí)就應(yīng)該使用execute方法來(lái)執(zhí)行CallableStatement。 CallableStatement類(lèi)是PreparedStatement的子類(lèi),因此CallableStatement對(duì)象可與PreparedStatement對(duì)象一樣帶有輸入?yún)?shù)。此外,CallableStatement對(duì)象還可帶輸出參數(shù)或輸入/輸出參數(shù)