JDBC技術(shù)基礎(chǔ)(完結(jié)版)_第1頁
JDBC技術(shù)基礎(chǔ)(完結(jié)版)_第2頁
JDBC技術(shù)基礎(chǔ)(完結(jié)版)_第3頁
JDBC技術(shù)基礎(chǔ)(完結(jié)版)_第4頁
JDBC技術(shù)基礎(chǔ)(完結(jié)版)_第5頁
已閱讀5頁,還剩17頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

1、第八章jdbc技術(shù)往往實際的項目中都需要用到主流的關(guān)系型數(shù)據(jù)庫,因此掌握jdbc技術(shù)是非常重要的。 本章主要介紹jdbc技術(shù)的基本原理,重點介紹jdbc技術(shù)體系中的常用接口和類,并通過實 例來說明用jdbc操作數(shù)據(jù)庫的過程。本章的基礎(chǔ)前提就是讀者已經(jīng)學(xué)過關(guān)于數(shù)據(jù)庫方面的 知識,并且熟悉常用的sql語句。8.1.1 jdbc基本概念jdbc,全稱為java database connectivity (java數(shù)據(jù)庫連接)。它由一-組用java語言 編寫的類和接口組成,是java開發(fā)人員和數(shù)據(jù)庫廠商達成的協(xié)議,也就是由sun公司定義 的一組接口,由數(shù)據(jù)庫廠商來實現(xiàn),并規(guī)定了 java開發(fā)人員訪問

2、數(shù)據(jù)庫所使用的方法的規(guī) 范。通過它可訪問各類關(guān)系數(shù)據(jù)庫。jdbc也是java核心類庫的組成部分。jdbc的最大特點是它獨立于具體的關(guān)系數(shù)據(jù)庫。與odbc (open database connectivity) 類似,jdbc api中定義了一些java類和接口,分別用來實現(xiàn)與數(shù)據(jù)庫的連接(connections)> 發(fā)送sql語句(sql suuements)、獲取結(jié)果集(result sets)以及其它的數(shù)據(jù)庫對象,使得 java程序能方便地與數(shù)據(jù)庫交互并處理所得的結(jié)果。jdbc的api在java.sqk javax.sql等包 中。jav“程序應(yīng)用jdbc, 一般由以下步驟。 注冊

3、加載一個數(shù)據(jù)庫驅(qū)動程序。 創(chuàng)建數(shù)據(jù)庫連接(connection)。 創(chuàng)建一個 statement (發(fā)送 sql)。 數(shù)據(jù)庫執(zhí)行sql語句。 用戶程序處理執(zhí)行sql語句的結(jié)果(包括結(jié)果集resultset)o 關(guān)閉連接(connection)等資源。由于數(shù)據(jù)庫不同,驅(qū)動程序的形式和內(nèi)容也不相同,主要體現(xiàn)在獲得連接的方式和相關(guān) 參數(shù)的不同。為了說明問題,本章采用的數(shù)據(jù)庫為sqlserver 2005,測試數(shù)據(jù)庫名為 jdbc_demo»庫中只有一張表person,如下圖所示。nnameagesex12: sara18玄3tom15男4james26男8kobe32男21jack50男2

4、3alex50男26wade28男圖81 person表示意圖其中id為自增長主鍵,name(string)> age(int)和sex(string)為字段。8.1.2 jdbc驅(qū)動程序及安裝jdbc驅(qū)動程序是用于特定數(shù)據(jù)庫的一套實現(xiàn)了 jdbc接口的類集。要通過jdbc來存 取某一特定的數(shù)據(jù)庫,必須有相應(yīng)的該數(shù)據(jù)庫的jdbc驅(qū)動程序,它往往是由生產(chǎn)數(shù)據(jù)庫的 廠家提供,是連接jdbc api與具體數(shù)據(jù)庫z間的橋梁。目前,主流的數(shù)據(jù)庫系統(tǒng)如oracle、 sqlserver> sybase> informix等都為客戶提供了相應(yīng)的驅(qū)動程序。由于歷史和廠商的原因,從驅(qū)動程序工作

5、原理分析,通常有四種類型。分別是: jdbc-odbc橋、部分java、部分本機驅(qū)動程序、中間數(shù)據(jù)訪問服務(wù)器和純java驅(qū)動程序。 分別說明如下。1、jdbc-odbc 橋,全稱是 jdbc-odbc bridge driver由于歷史原因,odbc 技術(shù) 比jdbc更早或更成熟,所以通過該種方式訪問一個odbc數(shù)據(jù)庫,是一個不錯的選擇。這 種方法主要原理是:提供了一種把jdbc調(diào)用映対為odbc調(diào)用的方法。因此,需要在客 戶機安裝一個odbc驅(qū)動。這種方式由于需要中間的轉(zhuǎn)換過程導(dǎo)致執(zhí)行效率低,目前比較 少用。實際上微軟的數(shù)據(jù)庫系統(tǒng)(如sqlserver和access)仍然保留了該種技術(shù)的支持

6、。2第二種類型的全稱是unative-api, partly java drivert,o這一類型的驅(qū)動程序是直接將 jdbc調(diào)用轉(zhuǎn)換為特定的數(shù)據(jù)庫調(diào)用,而不經(jīng)過odbc 了,執(zhí)行效率比第一種高。但該種方 法也存在轉(zhuǎn)換的問題,且這類驅(qū)動程序與第一種驅(qū)動程序類型一樣,也要求客八端的機器安 裝相應(yīng)的二進制代碼(驅(qū)動程序和廠商專有的apdo所以這類驅(qū)動程序應(yīng)用存在限制,如 不太適合用于applet等。3、第三種類型的全稱是“jdbcnct pure java driver 它的原理是將jdbc的調(diào)用轉(zhuǎn) 換為獨立于數(shù)據(jù)庫的網(wǎng)絡(luò)協(xié)議,并完全通過java驅(qū)動。這種類型的驅(qū)動程序不需要客戶端 的安裝和管理,

7、所以特別適合于具有中間件(middle tier)的分布式應(yīng)用,但目前這類驅(qū)動程序 的產(chǎn)品不多。4n第四種類型又稱為“native protocol, pure java driver”。它能將jdbc調(diào)用轉(zhuǎn)換為特 定數(shù)據(jù)庫直接使用的網(wǎng)絡(luò)協(xié)議,不需要安裝客戶端軟件,是百分z百的java程序。這種方 式的本質(zhì)是使用java sockets來連接數(shù)據(jù)庫,所以它特別適合于通過網(wǎng)絡(luò)使用后臺數(shù)據(jù)庫的 applet及web應(yīng)用,后面介紹的jdbc應(yīng)用主要使用該類型的驅(qū)動程序。目前,大部分數(shù) 據(jù)庫廠商提供了該類驅(qū)動程序的支持。用戶開發(fā)jdbc應(yīng)用系統(tǒng),首先需要安裝數(shù)據(jù)庫的驅(qū)動程序。以microsoft sq

8、lserver 2005為例,第一步是下載它的jdbc驅(qū)動jai包(如sqljdbc.jar),可以去微軟官方下載。第 二步,對于普通的java application應(yīng)用程序,只需要將jdbc驅(qū)動包復(fù)制到classpath 所指向的目錄下就可以了,這和普通的java類沒什么區(qū)別。而對于web應(yīng)用,通常將jdbc 驅(qū)動包放置在web-inf/lib g錄下即可。對于其它數(shù)據(jù)庫,可采用類似方法。8.1.3 一個簡單jdbc例子以下為一個最簡單的jdbc應(yīng)用代碼。jdbcexample.javaimport java.sql.*;/ 導(dǎo)入包public class jdbcexamplepubli

9、c static void main(string arg)string driver=null;/ 驅(qū)動程序名稱指定連接的數(shù)據(jù)庫urlstring ul=”jdbc:sqlserver:localhost: 1433;databasename二jdbc_demo”; try 加載驅(qū)動程序,此處為第四種類型驅(qū)動程序;driver=,'co m.m icrosoft.sqlserver.jdbc.sqlserverdriver”class.forname(dri ver);通過驅(qū)動程序管理器建立與數(shù)據(jù)庫的連接connection con = drivermanage匚getconnect

10、ion(url);創(chuàng)建執(zhí)行查詢的statement對象statement stmt = con.createstatement();/sql語句,用于查詢學(xué)生表中的姓名、年齡、和姓別string sql = "select name,age,sex from person"執(zhí)行查詢,查詢結(jié)果放在resultset的對象中resultset rs = stmt.executequery( sql);string name,sex;int age;打印出查詢結(jié)果。while(rs.next()獲得每一行屮每一列的數(shù)據(jù)n ame = rs.getstring(l);age = r

11、s.getlnt(2);sex = rs.getstring(3);system.out.println(name + 役 h + age+n,h +sex);找不到驅(qū)動程序,捕捉異常。如發(fā)生該錯誤,請檢查jdk版本是不是在1.1以上catch(classnotfoundexception e)system.out.println("錯誤:"+ e);1catch(sqlexception e)system.out.println("錯誤:"+ e);finally tryrs.close();stmt.close();con.close();catch

12、(sqlexception e 上面代碼,清晰地表達了應(yīng)用jdbc技術(shù)的基本步驟。需要說明的是: 所有與jdbc相關(guān)的操作代碼必須用my處理。一方血,jdbc中絕大多數(shù)方法都 被定義為拋出sqlexecption 常,該類界常屬于必須捕捉的界常,否則,編譯通 不過。另一方面,如果在一處發(fā)生異常,應(yīng)用程序就沒有必要進行下去了。如連接 數(shù)據(jù)庫失敗,就沒必要產(chǎn)生statement的實例了。 jdbc應(yīng)用小,一次數(shù)據(jù)庫會話結(jié)束,必須關(guān)閉數(shù)據(jù)庫連接資源,該資源是寶貴的, 會話期間,由用戶程序獨占,結(jié)束后,必須釋放。 結(jié)果集(resultset)xj象是一種數(shù)據(jù)容器,存放著滿足sql查詢條件的數(shù)據(jù)庫記錄。

13、 通過next()方法,對以遍歷所有記錄,通過getxxx()iij以得到指定行中的列值。關(guān) 于結(jié)果集的全面介紹在下面章節(jié)屮進行。8.2 jdbc常用接口、類介紹jdbc屮,定義了許多接口和類,但經(jīng)常使用的不是很多。以下介紹的是最常用的接口 和類,使初學(xué)者能夠盡快掌握jdbc技術(shù)。8.2.1 driver 接口driver接口在java.sql包中定義,每種數(shù)據(jù)庫的驅(qū)動程序都提供一個實現(xiàn)該接口的類, 簡稱driver類,應(yīng)用程序必須首先加載它。加載的目的就是創(chuàng)建自己的實例并向 java.sql.drivermanager類注冊該實例,以便驅(qū)動程療;管理類(drivermanager)對數(shù)據(jù)庫驅(qū)

14、動 程序的管理。通常情況下,通過java.lang.class類的靜態(tài)方法forname(string classname),加載欲連接 的數(shù)據(jù)庫驅(qū)動程序類,該方法的入口參數(shù)為欲加載的數(shù)據(jù)庫驅(qū)動程序完整類名。對于每種驅(qū) 動程序,其完整類名的定義也不一樣,以下做簡單說明。如果使用第一種類型驅(qū)動程序(jdbc-odbc),則其加載方法:class.forname("sun.jdbc.odbc.jdbcodbcdriver")0如果使用第四種類型驅(qū)動程序,則其加載方法: class.forname(mcom.microsoft.sqlserver.jdbc.sqlserverdr

15、iver"),這是 sqlserver2005 的 驅(qū)動程序加載方法,且如果版本不一樣,驅(qū)動程序名也會不同。同樣,其它數(shù)據(jù)庫(如mysql、oracle)的驅(qū)動程序加載方法也類同,這里不再說明。 若加載成功,系統(tǒng)會將驅(qū)動程序注冊到drivermanager類中。如果加載失敗,將拋岀 classnotfoundexception異常。以下是加載驅(qū)動程序的代碼。try cass.forname(drivernamey,/加載 jdbc 驅(qū)動器)catch (classnotfoundexception ex) ex.printstacktrace();需要注意的是,加載驅(qū)動程序行為屬于單

16、例模式,也就是說,整個數(shù)據(jù)庫應(yīng)用中,只加 載一次就可以了。&2.1 drivermanager 類數(shù)據(jù)庫驅(qū)動程序加載成功后,接下來就由drivermanager類來處理了,所以是該類是 jdbc的管理層,作用于用戶和驅(qū)動程序之間。它跟蹤可用的驅(qū)動程序,并在數(shù)據(jù)庫和相應(yīng) 驅(qū)動程序之間建立連接。另外,drivermanager類也處理諸如驅(qū)動程序登錄時間、登錄管理 和消息跟蹤等事務(wù)。drivermanager類的主要作用是管理用戶程序與特定數(shù)據(jù)庫(驅(qū)動程序)的連接。一般 情況下,drivermanager類可以管理多個數(shù)據(jù)庫驅(qū)動程序。當然,對于中小規(guī)模應(yīng)用項目, 可能只用到一種數(shù)據(jù)庫。jd

17、bc允許用戶通過調(diào)用drivermanager的getdriver> getdrivers 和registerdriver等方法,實現(xiàn)對驅(qū)動程序的管理,進一步,通過這些方法實現(xiàn)對數(shù)據(jù)庫連 接的管理。但多數(shù)情況下,不建議采用上述方法,如果沒有特殊要求,對于一般應(yīng)用項目, 建議讓drivermanager類自動管理。drivermanager類是用靜態(tài)方法getconnection來獲得用戶與特定數(shù)據(jù)庫連接。在建立連 接過程中,drivermanager將檢查注冊表中的每個驅(qū)動程序,查看它是否可以建立連接,有 時,可能有多個jdbc驅(qū)動程序可以和給定數(shù)據(jù)庫建立連接。例如,與給定遠程數(shù)據(jù)庫連接

18、 時,可以使用jdbc-odbc橋驅(qū)動程序、jdbc到通用網(wǎng)絡(luò)協(xié)議驅(qū)動程序或數(shù)據(jù)庫廠商提供 的驅(qū)動程序。在這種情況下,加載驅(qū)動程序的順序至關(guān)重要,因為drivermanager將使用它 找到的第一個可以成功連接到給定的數(shù)據(jù)庫驅(qū)動程序進行連接。用drivermanager建立連接,主要由以下兒種方法。 static connection getconnection(stnng urt), url 實際上標識給定數(shù)據(jù)庫(驅(qū)動程序), 它由三部分組成,用“:”分隔。格式為:jdbc:子協(xié)議名:子名稱。其中jdbc是唯一 的,jdbc只有這種協(xié)議;子協(xié)議名主要用于識別數(shù)據(jù)庫驅(qū)動程序的,不同的數(shù)據(jù) 庫有

19、不同的子協(xié)議名,如sqlsecvei*2005為“sqlsefver*”,子名稱為屬于專門驅(qū)動 程序的,對于sqlserver2005,指的是數(shù)據(jù)庫的名、服務(wù)端口號等信息,例如:“ /localhost: 1433;databasename=jdbc_demo ”。 static connection getconnection(slrng url, string username, siring password), 與第一 種相比,多了數(shù)據(jù)庫服務(wù)的登錄名和密碼,這個容易理解。8.2.2 connection 接 口connection對象代表數(shù)據(jù)庫連接,只有建立了連接,用戶程序才能操作數(shù)據(jù)

20、庫。連接是 jdbc屮最重要的接口使用頻度高,讀者必須掌握。connection接口的實例是由驅(qū)動程序管理類的靜態(tài)方法getconnection產(chǎn)生,數(shù)據(jù)庫連 接實例是寶貴的資源,它類似電話連接一樣,在一個會話期內(nèi),是由用戶程序獨占的,且需 要耗費內(nèi)存的,因此,每個數(shù)據(jù)庫的最大連接數(shù)是受限的。所以,用戶程序訪問數(shù)據(jù)庫結(jié)束 后,必須及時關(guān)閉連接,以方便其它用戶使用該資源。connection接口的主要功能(或方法) 是獲得各種發(fā)送sql語句的運載類(以下會介紹),以下簡要列出該接口的主要方法。 close()方法:關(guān)閉到數(shù)據(jù)庫的連接,在使用完連接后必須關(guān)閉,否則連接會保持一 段比較長的吋i

21、9;可,直到超吋。 commito方法:提交對數(shù)據(jù)庫的更改,使更改生效。這個方法只有調(diào)用了 setautocommit(false)*法后才有效,否則對數(shù)據(jù)庫的更改會自動提交到數(shù)據(jù)庫。 createstatement()方法:創(chuàng)建一個 statement, statement 用于執(zhí)行 sql 語句。 createstatement(int resultsettype, int resultsetconcuirency)方法:倉u建一個 statement, 并且產(chǎn)生指定類型的結(jié)果集(resultsct)。關(guān)于相關(guān)參數(shù)的介紹在下面章節(jié)屮會詳 細介紹。 getautocommit()方法:為這個

22、連接對象,獲取當前auto-commit模式。 getmetadata()方法:獲得一個databasemetadata刈像,其中包含了關(guān)于數(shù)據(jù)庫的元 數(shù)據(jù)。 isclosed()方法:判斷連接是否關(guān)閉。 preparestatement(stringsql)方法:使用指定的sql語句創(chuàng)建一個預(yù)處理語句,sql 參數(shù)中往往包含一個或者多個“?”占位符。 rollback()方法:冋滾當前執(zhí)行的操作,只有調(diào)用了 setautocommit(false)才可以使 用。 setautocommit(boolean autocommil)方法:設(shè)置操作是否自動提交到數(shù)據(jù)庫,默認 情況下是trueo由于

23、數(shù)據(jù)庫不同,驅(qū)動程序的形式和內(nèi)容也不相同,主要體現(xiàn)在獲得連接的方式和相關(guān) 參數(shù)的不同。因此,在jdbc項目,根據(jù)面向?qū)澫蟮脑O(shè)計思想(封裝變化),一般把連接管 理設(shè)計成為一個類:連接管理器類,主要負責連接的獲得和關(guān)閉。以下是連接管理器dbconnection.class的代碼。package dao;import java.sql.*;public class dbconnection 數(shù)據(jù)庫的urlprivate static string url ="jdbc:sqlserver:/localhost: 1433;databasename =jdbc_demo"priva

24、te static string userncune = "sa”;數(shù)據(jù)庫用戶名private static string password = ”123456"/數(shù)據(jù)庫密碼/jdbc驅(qū)動器名稱private static string drivername = "com.microsoft.sqlserver. jdbc.sqlserverdriveru; static try cass.forname(drivernamey,/加載 jdbc 驅(qū)動器 catch (exception ex) ex.printstacktrace();ipublic stati

25、c connection getconn() try connection conn = drivermanager etconnecti(m(url,userncune, password);systems/.printin(”連接數(shù)據(jù)庫成功“);return conn; catch (sqlexception ex) systemw/.println(h 連接數(shù)據(jù)庫失敗“); ex.printstacktrace();return null;public static void close(connection conn, statement stm resultset rs) tryif

26、(rs != null)rs.close();if(stm!=null)stm.close();if (conn != null)conn.close();system, ow.println(”數(shù)據(jù)庫連接成功釋放“);)catch (sqlexception ex) i1以下為測試代碼。public class testjdbcpublic static void main(stringn args) dbconnection.gerco 諷); dbconnection.czose();控制臺打印出“連接數(shù)據(jù)庫成功”、“數(shù)據(jù)庫連接成功釋放”的語句,說明jdbc連接數(shù) 據(jù)庫已經(jīng)成功。從上面的

27、代碼可以看出,主要有兩個操作,首先使用class.forname方法加 載驅(qū)動器,接著使用drivermanager.getconnection方法得到數(shù)據(jù)庫連接。由于加載驅(qū)動器, 在整個應(yīng)用系統(tǒng)中,只有一次,所以采用static程序塊技術(shù)來實現(xiàn)。8.2.3 statementstatement> preparedstatement 和 callablestatement,這 3 個接口 都是用來執(zhí)行 sql 語句 的,都由connction中的相關(guān)方法產(chǎn)生,但它們有所不同。statement接口用于執(zhí)彳亍靜態(tài)sql 語句并返冋它所生成結(jié)果集對象:preparedstatement表示帶

28、in或不帶in的預(yù)編譯sql語 句對象,sql語句被預(yù)編譯并存儲在preparedstatement對象中;callablestatement用丁執(zhí)行 sql存儲過程的接口。下面分別介紹著3個接口的使用。1、statement 接口因為statement是一個接口,它沒用構(gòu)造函數(shù),所以不能直接創(chuàng)建一個實例。創(chuàng)建一個 statement對象必須通過connection接i i提供的createstatement方法進行創(chuàng)建。英代碼片段 如下:statement statement=connection.createstatement();創(chuàng)建完statement對象后,用丿程序就可以根據(jù)需要調(diào)用

29、它的常用方法,如executequery> executeupdatex executeexecutebatch 等方法。executequery 力-法該方法用于執(zhí)行產(chǎn)生單個結(jié)果集的sql語句,如select語句,該方法返回一個結(jié)果集 resultset對象。完整的方法聲明如下:resultset executequery(string sql) throws sqlexception下血給出一個實例,使用executequery方法執(zhí)彳亍查詢person表的sql語句,并返回結(jié) 果集。jdbctest.javaimport dao.*;import sql.*;public clas

30、s jdbctestpublic static void main(stringn args) conn ection connection = dbcorrn ection. gw/c(皿();statement statement = null;resultset resultset = null;try statement = connection.createstatement();string sql = '"select name,age,sex from person1'resultset = statement.executequery(sql);wh

31、ile(resultset.next()system.m/.println(hname:n+resultset.getstring(nnameh);system.mlprintln(,'age:n+resultset.getstring(nagen);system.<?hlprintln(,lsex:,+resultset.getstring(ksexh); catch (sqlexception e) e.printstacktrace(); finally dbconnection.c7aye(connection, statement, resultset);以上代碼中,用

32、到了連接管理器類dbconnectioncexecuteupdate 方法該方法執(zhí)行給定sql語句,該語句可能為insert、update或delete語句,或者 不返回任何內(nèi)容的sql語句(如sql ddl語句)。完整的方法聲明如下:int executeupdate(string sql) throws sqlexception對于sql數(shù)據(jù)操作語言(dml)語句,返回行計數(shù);對于什么都不返回的sql語句, 返回正數(shù)0。下面給出一個實例,使用executeupdate方法執(zhí)行插入sql語句。public static void main(string args) conn ecti on

33、conn ection = dbconnection.g刃 comz();statement statement = null;resultset resultset = null;int rowcount;try statement = connection.createstatement();string sql = insert into person(name,age,sex) values(tom;15,男丁;rowcount = statement.executeupdate(sql);system.our.println("插入所影響的行數(shù)為"+rowcoun

34、t+"行"); catch (sqlexception e) e.printstacktrace(); finally dbconnection.c7ave(connection, statement, resultset);execute 方法執(zhí)行給定的sql語句,該語句可能返冋多個結(jié)果。在某些(不常見)情形下,單個sql 語句可能返回多個結(jié)果集和或更新記錄數(shù),這一點通??梢院雎裕钦趫?zhí)行已知可能返 回多個結(jié)果的存儲過程或者動態(tài)執(zhí)行未知sql字符串。一般情況下,execute方法執(zhí)行 sql語句并返回第一個結(jié)果的形式。然后,用戶程序必須使用方法getresultset

35、或 getupdatecount來獲取結(jié)果,使用getmoreresults來移動后續(xù)結(jié)果。該方法的完整聲明如 下:boolean execute(string sql) throws sqlexception該方法是一個通用方法,既可以執(zhí)行查詢語句,也可以執(zhí)行修改語句,該方法可以用來 處理動態(tài)的未知的sql語句。下面的實例使用execute方法執(zhí)行一個用戶輸入的sql語句, 并返回結(jié)果。public static void main(string args) connection connection = dbconnection.g刃statement statement = null;r

36、esultset resultset = null;int rowcount;boolean isresultset;try statement = connection.createstateme nt();string sql = joptionpanq.showinputdialogc 請輸入一個 sql 語句:”); isresultset = statement.execute(sql);if(isresultset)resultset = statement.getresultset();while(resultset.next()system.m/.println(hname:h

37、+resultset.getstring(nnamen); system.>wlprintln(nage:n+resultset.getstring(magen); system.6?wr.println(nsex:n+resultset.getstring(nsexn);elserowcount = statement.getupdatecount();system, ou/.println(” 所更新的行數(shù)為"4-rowcount+m 行”);)catch (sqlexception e) e.printstacktrace(); finally dbconnection.

38、c7<75e(connection, statement, resultset);對于以上代碼,讀者可以自行編寫一個測試類。executebatch 方法將一批命令提交給數(shù)據(jù)庫來執(zhí)行,如果全部命令執(zhí)行成功,則返冋一個和添加命令時順 序一樣的整型數(shù)組,數(shù)組元素的排序?qū)?yīng)于批中的命令,批中的命令根據(jù)被添加到批中的順 序排序,數(shù)組中的元素的值可能為以下值之一: 大于等于0的數(shù),指示成功處理了命令,其值為執(zhí)行命令所影響數(shù)據(jù)庫中行數(shù)的更 新計數(shù)。 success_no_info,指示成功執(zhí)行了命令,但受影響的行數(shù)是未知的。如果批 量更新中的命令之一無法正確執(zhí)行,方法則拋出batchupdateex

39、ception,并且jdbc 驅(qū)動程序可能繼續(xù)處理批處理中的剩余命令,也可能不執(zhí)行。無論如何,驅(qū)動程序 的行為必須與特定的dbms 一致,要么始終繼續(xù)處理命令,要么永遠不繼續(xù)處理 命令。 execute_failed ,指示未能成功執(zhí)行命令,僅當命令失敗后,驅(qū)動程序繼續(xù)處 理命令吋出現(xiàn)。該方法完整的聲明如下:int|j executebatch() throws sqlexception對于批處理操作,另外還有兩個輔助方法:addbatch,向批處理中加入一個更新語句; clearbatch,清空批處理屮的更新語句。在下面的實例屮使用executebatch方法來執(zhí)行多個 insert語句向p

40、erson數(shù)據(jù)表插入多條記錄,并顯示返回的更新計數(shù)數(shù)組。public static void main(string args) connection connection = dbcormection.g刃conn();statement statement = null;resultset resultset = null;int rowcount;try stateme nt = corm ectio n.createstateme nt();string sqll = "insert into person(name,age,sex) values(fkober,32;男&#

41、39;)”;string sq!2 = "insert into person(name,age,sex) valuesckobe232;男')”;string sq!3 = "insert into person(name,age,sex) values(fkobe332;男')”; statement.addbatch(sql 1);statement.addbatch(sql2);statenient.addbatch(sql3);rowc ount = statem en t.executebatch();for(int i=0;i<rowco

42、unt.length;i+) system.om.println(”第”+(i+l)+”條語句執(zhí)行影響的行數(shù)為 h+rowcounti+"行”);1 catch (sqlexception e) e.printstacktrace(); finally dbconnection.c7ase(connection, statement, resultset);2x preparedstatementpreparedstatement 是 statement 的子接口,preparedstatement 的實例 la經(jīng)包含編譯的 sql 語句,所以它的執(zhí)行速度快于statemento p

43、reparedstatement的對象創(chuàng)建同樣需要connection 接口提供的方法preparestatement方法,同時礙要制定sql語句。核心代碼如下:connection connection = dbconnection.gerc/?/?();string sql = "delete from person where name = ?n;preparedstatement pstm = connection.preparestatement(sql);上面的sql語句中有“? ”號,指的是sql語句中的占位符,表示sql語句中的可 替換參數(shù),也稱作in參數(shù),在執(zhí)行前必

44、須賦值。因此preparedstatement還添加了一些設(shè)置 in參數(shù)的方法。同時,execute> executequery和executeupdate方法也變了,無需再傳入sql 語句,因為前而已經(jīng)指定了 sql語句。下面給出的是preparedstatement執(zhí)行sql的一個實 例:public static void main(string args) conn ecti on conn ection = dbconnection.g刃 comz();preparedstatement preparedstatement = null;resultset resultset

45、= null;int isresultset;try string sql = udelete from person where name = ?n; preparedstatement=connection.preparestatement(sql); preparedstatement.setstring( 1, halexn);isresultset = preparedstatement.executeupdate();)catch (sqlexception e) e.printstacktrace(); finally dbconnection.c/<95e(connect

46、ion, preparedstatement, resultset);從上述例子分析,用preparedstatement來代替statement會使代碼多出幾行,但代碼的 可讀性和可維護性提高了,為了說明問題,下面再舉一個例子。 stmt.executeupdate(ninsert into lb_name (col 1 ,col2,col2,col4) values('“+varl+”','”+vai'2+”',“+vai3+”f+var4+”')“);perstmt = con.preparestatement(minsert into t

47、b_name (coli,col2,col2,col4) values (?,?,?,?)”); perstmt.setstring( 1 ,varl);perstmt.setstring(2,var2);perstmt.setstring(3,var3);perstmt.setstring(4,var4);perstmt.executeupdate(); 上述代碼屮,第1、2行表示用statement來實現(xiàn)插入操作,其余行表示用 preparedstatement完成同樣工作。preparedstatement的setxxx (序號,值)用來設(shè)置相關(guān)“ ? ” 位值,序號表示“? ”的位置,

48、上面例子中,假設(shè)四個字段的數(shù)據(jù)類型都是“string”,若有 其它類型,如int,則設(shè)值方法改為對應(yīng)的setlnto用preparedstatemen接口,不但代碼的可讀性好了,且在執(zhí)行效率方面,得以大大提高。 每一種數(shù)據(jù)庫都會盡最大努力對預(yù)編譯語句提供最大的性能優(yōu)化,因為預(yù)編譯語句有可 能被重復(fù)調(diào)用,所以sql語句在被數(shù)據(jù)庫系統(tǒng)的編譯器編譯后,其執(zhí)行代碼被緩存下來, 下次調(diào)用時,只要是相同的預(yù)編譯語句(如插入記錄操作),就不蠱要編譯了,只要將參數(shù) 直接傳入已編譯的語句,就會得到執(zhí)行,這個過程類似于函數(shù)調(diào)用。而對于statement,即 使是相同操作,由于每次操作的數(shù)據(jù)不同(如插入不同記錄),

49、數(shù)據(jù)庫必須重新編譯才能執(zhí) 行。需要說明的是,并不是所有預(yù)編譯語句在任何時候都一定會被緩存,數(shù)據(jù)庫本身會用一 種策略,比如使用頻度等因素來決定什么吋候不再緩存已有的預(yù)編譯結(jié)果,以保存有更多的 空間存儲新的預(yù)編譯語句。其實,用preparedstatemen接口,不但效率高,且安全性好,可以防止惡意的sql注 入,下面代碼所示。string sql = "select * from tb_name where name= <"+vamaitie+u< and passwd=4"+varpasswd+"4h;以上代碼是常用的登錄處理sql語句,用戶

50、從登錄頁面輸入用戶名和密碼,應(yīng)用程序 用varname和varpasswd來接受,并查詢數(shù)據(jù)庫。若結(jié)果集有一條記錄(假設(shè)用戶名不能重 復(fù)),則表示登錄成功。一般情況下,這種處理是沒有問題的,但如果惡意用戶用下列方法 輸入用戶名和密碼,則情形大不同了。用戶名:任意取,如"abc”。密碼:輸入:'or '1 '二'1。若以上輸入,貝ij, sql語句成為:select * from tb_name =' abc ' and passwd ='' or t ' ='1 ';因為t '二'

51、1 '肯定成立,所以可以通過任何驗證。更有甚者,把'drop table tb_name; 作為varpasswd值傳入進來,當然,有些數(shù)據(jù)庫是不會讓你成功的,但也有很多數(shù)據(jù)庫可以 使這些語句得到執(zhí)行。而如果使用預(yù)編譯語句,就不會產(chǎn)生這些問題。因此,建議盡量使用 預(yù)編譯語句(preparedstatement)。3.、callablestatementcallablestatement 是 preparedstatement 的子接口,用于執(zhí)行 sql 存儲過程的接口 jdbc 的api提供了一個存儲過程的sql轉(zhuǎn)義語法,該語法允許對所有rdbms使用標準方式調(diào) 用存儲過程。此

52、轉(zhuǎn)義語法有一個包含結(jié)果參數(shù)的形式和一個不包含結(jié)果參數(shù)的形式。如果使 用結(jié)果參數(shù),則必須將其注冊為out參數(shù)。其他參數(shù)可用于輸入、輸岀或同時用于二者。 參數(shù)是根據(jù)編號順序引用的,第一個參數(shù)的編號為1。以下為示意代碼。?= call <procedure-name>f(<arg 1 >,<arg2>,.)call <procedure-name>(<argl>,<arg2>,.)in參數(shù)值是通過set方法(繼承自preparedstatement的)來設(shè)置。在執(zhí)行存儲過程之前, 必須注冊所有out參數(shù)的類型;它們的值是在執(zhí)行后

53、,通過該類提供的get方法獲取。 callablestatement可以返回一個或多個resultset對象°resul(set對象使用繼承來自statement 的相關(guān)方法處理。為了獲得最大的可移植性,resultset對象和更新計數(shù)應(yīng)該在獲得輸出參 數(shù)值之前被處理。下面給出的是callablestatement執(zhí)行sql的一個實例:public static void main(string args) connection connection = dbconnection.g刃com();callablestatement callablestatement = null;r

54、esultset resultset = null;int isresultset;string sql = "call addperson (lucaso/男 callablestatement = connection.preparecall(sql); isresultset = callablestatement.executeupdate(); catch (sqlexception e) e.printstacktrace(); finallydbconnection-cfo5e(connection, callablestatement, resultset); 8.2

55、.4 resultset 結(jié)果集statement執(zhí)行一條查詢sql語句后,會得到一個resultset對彖,稱之為結(jié)果集,它是 存放每行數(shù)據(jù)記錄的集合。有了這個結(jié)果集,用戶程序就可以從這個対象中檢索出所需的數(shù) 據(jù)并進行處理(如用表格顯示)。resultset對象具有指向當前數(shù)據(jù)行的光標。最初,光標被 置于第一行z前(bcforcfirst), next方法將光標移動到下一行,該方法返回類型為boolean 型,若resultset對象沒有下一行時,返回false,所以可以用while循環(huán)來迭代結(jié)果集。默 認的resultset對彖不可更新,僅有一個向前移動的光標。因此,只能迭代它一次,并且只

56、 能從第一行到最后一行的順序進行。當然,可以生成可滾動和可更新的resultset對象。另 外,結(jié)果集對象與數(shù)據(jù)庫連接(connection)是密切相關(guān)的,若連接被關(guān)閉,則建立在該連接 上的結(jié)果集對象被系統(tǒng)回收,一般情況下,一個連接,只能產(chǎn)生一個結(jié)果集。1、默認的resultset對象resultset對象可由三種statement語句來創(chuàng)建,分別需要調(diào)用connection接口的方法創(chuàng) 建。以下為三種方法的核心代碼。statement stmt = connection.createstatement();resultset rs=stmt. executequery(sql);prepar

57、edstatement pstmt=connection.preparestatement(sql);resultset rs=pstmt.executequeiy();callablestatement cstmt= connection.preparecall(sql);resultset rs=cstmt.executequery();resultset對象的常用方法主要包括-行操作方法和列操作方法,這些方法可以讓用戶程 序方便地遍歷結(jié)杲集屮所有數(shù)據(jù)元素。下面分別說明。 boolean next()行操作方法,將游標從當前位置向前移一行,當無下一行時返回falseo 游標的初始位置在第一

58、行前面,所以要訪問結(jié)果集數(shù)據(jù),首先要調(diào)用該方法。 getxxx(int columnindex)列方法系列,獲取所在行指定列的值?!皒xx”實際上與列(字段)的數(shù)據(jù)類型有關(guān),若列為string型,則方法為getstring,若為int型,則 為getlnto columnindex表示列號,其值從1開始編號,如i:第2列,則值為2。 getxxx(string columnname)列方法系列,獲取所在行指泄列的值。coluitinname表 示列名(字段名)。如:getstring( "name"),表示得到當前行字段名為“name” 的列值。下面的實例展示了默認的resultset使用。public static voi

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論