《Java程序設(shè)計(jì)教程》課件第十四章:JDBC與MySQL編程_第1頁(yè)
《Java程序設(shè)計(jì)教程》課件第十四章:JDBC與MySQL編程_第2頁(yè)
《Java程序設(shè)計(jì)教程》課件第十四章:JDBC與MySQL編程_第3頁(yè)
《Java程序設(shè)計(jì)教程》課件第十四章:JDBC與MySQL編程_第4頁(yè)
《Java程序設(shè)計(jì)教程》課件第十四章:JDBC與MySQL編程_第5頁(yè)
已閱讀5頁(yè),還剩50頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡(jiǎn)介

本章學(xué)習(xí)目標(biāo):●

了解JDBC概念以及驅(qū)動(dòng)類(lèi)型●

掌握使用JDBC連接MySQL數(shù)據(jù)庫(kù)的基本步驟●

掌握數(shù)據(jù)庫(kù)環(huán)境的搭建●

掌握使用JDBC訪問(wèn)數(shù)據(jù)庫(kù)的步驟●

掌握使用JavaAPI操作數(shù)據(jù)庫(kù)●

掌握數(shù)據(jù)庫(kù)事務(wù)的使用第十四章JDBC與MySQL編程第1節(jié)partJDBC基礎(chǔ)

通過(guò)使用JDBC,Java程序可以輕松地操作各種主流數(shù)據(jù)庫(kù),例如,Oracle、MSSQLServer、MySQL等。由于Java語(yǔ)言本身的跨平臺(tái)性,所以使用JDBC編寫(xiě)的程序不僅可以實(shí)現(xiàn)跨數(shù)據(jù)庫(kù),還具有跨平臺(tái)性和可移植性。使用JDBC訪問(wèn)數(shù)據(jù)庫(kù)具有操作簡(jiǎn)單、獲取方便且安全可靠等優(yōu)勢(shì)。JDBC基礎(chǔ)本節(jié)概述JDBC(JavaDatabaseConnectivity,Java數(shù)據(jù)庫(kù)連接)是一種執(zhí)行SQL語(yǔ)句的JavaAPI。程序可以通過(guò)JDBCAPI連接到關(guān)系數(shù)據(jù)庫(kù),并使用SQL結(jié)構(gòu)化語(yǔ)言來(lái)完成對(duì)數(shù)據(jù)庫(kù)的增、刪、改、查等操作。與其他數(shù)據(jù)庫(kù)編程語(yǔ)言相比,JDBC為數(shù)據(jù)開(kāi)發(fā)者提供了標(biāo)準(zhǔn)的API,使用JDBC開(kāi)發(fā)的數(shù)據(jù)庫(kù)應(yīng)用程序可以訪問(wèn)不同的數(shù)據(jù)庫(kù),并在不同平臺(tái)上運(yùn)行,既可以在Windows平臺(tái)上運(yùn)行,也可以在UNIX平臺(tái)上運(yùn)行。JDBC程序訪問(wèn)不同的數(shù)據(jù)庫(kù)時(shí),需要數(shù)據(jù)庫(kù)廠商提供相應(yīng)的驅(qū)動(dòng)程序。通過(guò)JDBC驅(qū)動(dòng)程序的轉(zhuǎn)換,使得相同的代碼在訪問(wèn)不同的數(shù)據(jù)庫(kù)時(shí)運(yùn)行良好。JDBC驅(qū)動(dòng)示意圖如圖14.1所示。14.1.1JDBC簡(jiǎn)介JDBC簡(jiǎn)介JDBC應(yīng)用程序可以對(duì)數(shù)據(jù)庫(kù)進(jìn)行訪問(wèn)和操作,JDBC訪問(wèn)數(shù)據(jù)庫(kù)時(shí)主要完成以下工作:

●建立與數(shù)據(jù)庫(kù)的連接;

●執(zhí)行SQL語(yǔ)句;

●獲取執(zhí)行結(jié)果。

數(shù)據(jù)庫(kù)驅(qū)動(dòng)程序是JDBC程序和數(shù)據(jù)庫(kù)之間的轉(zhuǎn)換層,數(shù)據(jù)庫(kù)驅(qū)動(dòng)程序負(fù)責(zé)將JDBC調(diào)用映射成特定的數(shù)據(jù)庫(kù)調(diào)用,JDBC訪問(wèn)示意圖如圖14.2所示。14.1.2JDBC驅(qū)動(dòng)JDBC驅(qū)動(dòng)

當(dāng)今市場(chǎng)上主流數(shù)據(jù)庫(kù)都提供了JDBC驅(qū)動(dòng)程序,甚至一些流行的數(shù)據(jù)庫(kù)還提供了多種不同版本的JDBC驅(qū)動(dòng)程序。JDBC驅(qū)動(dòng)程序有以下4種類(lèi)型:

●JDBC-ODBC橋:是最早實(shí)現(xiàn)的JDBC驅(qū)動(dòng)程序,主要目的是快速推廣JDBC。ODBC(OpenDatabaseConnectivity,開(kāi)放數(shù)據(jù)庫(kù)連接)是通過(guò)一組通用的API訪問(wèn)不同的數(shù)據(jù)庫(kù)管理系統(tǒng),也需要各數(shù)據(jù)庫(kù)廠商提供相應(yīng)的驅(qū)動(dòng)程序,而ODBC則對(duì)這些驅(qū)動(dòng)程序進(jìn)行管理。JDBC-ODBC橋驅(qū)動(dòng)是將JDBCAPI映射到ODBCAPI,驅(qū)動(dòng)速度很慢,只適用于訪問(wèn)沒(méi)有其他JDBC驅(qū)動(dòng)的數(shù)據(jù)庫(kù)。由于Java語(yǔ)言的廣泛應(yīng)用,所有數(shù)據(jù)庫(kù)廠商都提供了JDBC驅(qū)動(dòng),因此在Java8中不再支持JDBC-ODBC數(shù)據(jù)訪問(wèn)方式。JDBC驅(qū)動(dòng)14.1.2

●本地API驅(qū)動(dòng):直接將JDBCAPI映射成數(shù)據(jù)庫(kù)特定的客戶端API,包含特定的數(shù)據(jù)庫(kù)本地代碼,用于訪問(wèn)特定數(shù)據(jù)庫(kù)的客戶端。本地API驅(qū)動(dòng)比起JDBC-ODBC橋執(zhí)行效率要高,但是仍然需要在客戶端加載數(shù)據(jù)庫(kù)廠商提供的代碼庫(kù),不適合基于網(wǎng)絡(luò)的應(yīng)用。本地API驅(qū)動(dòng)雖然速度有所提升,但相對(duì)后面兩種JDBC驅(qū)動(dòng)還是不夠高。

●網(wǎng)絡(luò)協(xié)議驅(qū)動(dòng):將JDBC調(diào)用翻譯成中間件供應(yīng)商的協(xié)議,然后再由中間件服務(wù)器翻譯成數(shù)據(jù)庫(kù)訪問(wèn)協(xié)議。網(wǎng)絡(luò)協(xié)議驅(qū)動(dòng)是基于服務(wù)器的,不需要在客戶端加載數(shù)據(jù)庫(kù)廠商提供的代碼庫(kù),且執(zhí)行效率比較好,便于維護(hù)和升級(jí)。

●本地協(xié)議驅(qū)動(dòng):是純Java編寫(xiě)的,可以直接連接到數(shù)據(jù)庫(kù)。本地協(xié)議驅(qū)動(dòng)不需要將JDBC的調(diào)用傳給ODBC,或本地?cái)?shù)據(jù)庫(kù)接口,或中間層服務(wù)器,因此執(zhí)行效率非常高;而且根本不需要在客戶端或服務(wù)器裝載任何軟件或驅(qū)動(dòng)。本地協(xié)議驅(qū)動(dòng)是智能的,能夠知道數(shù)據(jù)庫(kù)使用的底層協(xié)議,是目前最流行的JDBC驅(qū)動(dòng)。通常JDBC訪問(wèn)數(shù)據(jù)庫(kù)時(shí)建議使用第4種本地協(xié)議驅(qū)動(dòng),該驅(qū)動(dòng)使用純Java編寫(xiě),且避開(kāi)了本地代碼,減少了應(yīng)用開(kāi)發(fā)的復(fù)雜性,降低了產(chǎn)生沖突和出錯(cuò)的可能。JDBC驅(qū)動(dòng)14.1.2JDBCAPI提供了一組用于與數(shù)據(jù)庫(kù)進(jìn)行通信的接口和類(lèi),這些接口和類(lèi)都定義在java.sql包中,常用的接口和類(lèi)如表14-1所示。14.1.3JDBC

APIJDBC

API

需要注意的是:使用JDBCAPI中的類(lèi)或接口訪問(wèn)數(shù)據(jù)庫(kù)時(shí),容易引發(fā)SQLException異常,SQLException異常類(lèi)是檢查型異常,需要放在try…catch語(yǔ)句中進(jìn)行異常處理,SQLException是JDBC中其他異常類(lèi)型的基礎(chǔ)。1.DriverManager類(lèi)DriverManager是數(shù)據(jù)庫(kù)驅(qū)動(dòng)管理類(lèi),用于管理一組JDBC驅(qū)動(dòng)程序的基本服務(wù)。應(yīng)用程序和數(shù)據(jù)庫(kù)之間可以通過(guò)DriverManager建立連接,其常用的靜態(tài)方法如表14-2所示。JDBC

API14.1.32.Connection接口Connection接口用于連接數(shù)據(jù)庫(kù),每個(gè)Connection對(duì)象代表一個(gè)數(shù)據(jù)庫(kù)連接會(huì)話,要想訪問(wèn)數(shù)據(jù)庫(kù),必須先獲得數(shù)據(jù)庫(kù)連接。一個(gè)應(yīng)用程序可與單個(gè)數(shù)據(jù)庫(kù)建立一個(gè)或多個(gè)連接,也可以與多個(gè)數(shù)據(jù)庫(kù)建立連接。通過(guò)DriverManager類(lèi)的getConnection()方法可以返回一個(gè)Connection對(duì)象,該對(duì)象中提供了創(chuàng)建SQL語(yǔ)句的方法,以完成基本的SQL操作,同時(shí)為數(shù)據(jù)庫(kù)事務(wù)提供了提交和回滾的方法。Connection接口中常用的方法如表14-3所示。JDBC

API14.1.33.Statement接口Statement接口一般用于執(zhí)行SQL語(yǔ)句。在JDBC中要執(zhí)行SQL查詢(xún)語(yǔ)句的方式有一般查詢(xún)(Statement)、參數(shù)查詢(xún)(PreparedStatement)和存儲(chǔ)過(guò)程(CallableStatement)三種方式。Connection接口中提供的createStatement()、prepareStatement()和prepareCall()方法分別返回一個(gè)Statement對(duì)象,PreparedStatement對(duì)象和CallableStatement對(duì)象。Statement、PreparedStatement和CallableStatement三個(gè)接口具有繼承關(guān)系,其中PreparedStatement是Statement的子接口,而CallableStatement又是PreparedStatement的子接口。Statement接口的主要功能是將SQL語(yǔ)句傳送給數(shù)據(jù)庫(kù),并返回SQL語(yǔ)句的執(zhí)行結(jié)果。Statement提交的SQL語(yǔ)句是靜態(tài)的,不需要接收任何參數(shù),SQL語(yǔ)句可以包含以下三種類(lèi)型的語(yǔ)句:

●SELECT查詢(xún)語(yǔ)句;

●DML語(yǔ)句,如INSERT、UPDATE或DELETE;

●DDL語(yǔ)句,如CREATETABLE和DROPTABLE。JDBC

API14.1.3Statement接口中常用的方法及功能如表14-4所示。JDBC

API

需要注意的是:closeOnCompletion()和isCloseOnCompletion()方法是從Java7開(kāi)始新增的方法,executeLargeUpdate()方法是從Java8開(kāi)始新增的方法,在開(kāi)發(fā)過(guò)程中使用這幾個(gè)方法時(shí)需要注意JDK的版本??紤]到目前應(yīng)用程序所處理的數(shù)據(jù)量越來(lái)越大,使用executeLargeUpdate()方法具有更好的適應(yīng)性,但目前有的數(shù)據(jù)庫(kù)驅(qū)動(dòng)暫不支持該方法,例如MySQL驅(qū)動(dòng)。14.1.34.ResultSet接口ResultSet接口用于封裝結(jié)果集對(duì)象,該對(duì)象包含訪問(wèn)查詢(xún)結(jié)果的方法。使用Statement中的executeQuery()方法可以返回一個(gè)ResultSet結(jié)果集的對(duì)象,該對(duì)象封裝了所有符合查詢(xún)條件的記錄。ResultSet具有指向當(dāng)前數(shù)據(jù)行的游標(biāo),并提供了許多方法來(lái)操作結(jié)果集中的游標(biāo),同時(shí)還提供了一套getXXX()方法對(duì)結(jié)果集中的數(shù)據(jù)進(jìn)行訪問(wèn),這些方法可以通過(guò)列索引或列名獲得數(shù)據(jù)。ResultSet接口中常用的方法如表14-5所示。JDBC

API14.1.3ResultSet對(duì)象具有指向當(dāng)前數(shù)據(jù)行的游標(biāo)。最初游標(biāo)位于第一行之前,每調(diào)用一次next()方法,游標(biāo)會(huì)自動(dòng)向下移一行,從而可以從上到下依次獲取所有數(shù)據(jù)行。getXXX()方法用于對(duì)游標(biāo)所指向的行的數(shù)據(jù)進(jìn)行訪問(wèn)。在使用getXXX()方法取值時(shí),數(shù)據(jù)庫(kù)的字段數(shù)據(jù)類(lèi)型要與Java的數(shù)據(jù)類(lèi)型相匹配,例如,數(shù)據(jù)庫(kù)中的整數(shù)字段對(duì)應(yīng)Java數(shù)據(jù)類(lèi)型中的int類(lèi)型,此時(shí)使用getInt()方法來(lái)讀取該字段中的數(shù)據(jù)。常用的SQL數(shù)據(jù)類(lèi)型和Java數(shù)據(jù)類(lèi)型之間的對(duì)應(yīng)關(guān)系如表14-6所示。JDBC

API14.1.3第2節(jié)part數(shù)據(jù)庫(kù)環(huán)境搭建14.2.1創(chuàng)建數(shù)據(jù)庫(kù)表

本章JDBC數(shù)據(jù)庫(kù)訪問(wèn)基于MySQL數(shù)據(jù)庫(kù),因此所有的代碼及環(huán)境都是基于MySQL數(shù)據(jù)庫(kù)的。在進(jìn)行數(shù)據(jù)庫(kù)訪問(wèn)操作之前,需要先創(chuàng)建數(shù)據(jù)庫(kù)和表并錄入測(cè)試數(shù)據(jù)。在root用戶下創(chuàng)建student數(shù)據(jù)庫(kù),并在該庫(kù)下創(chuàng)建t_user表,并添加測(cè)試數(shù)據(jù),其SQL代碼如下所示。創(chuàng)建數(shù)據(jù)庫(kù)表創(chuàng)建數(shù)據(jù)庫(kù)表

【代碼14.1】student.sqlCREATEDATABASE`student`;CREATETABLE`t_user`(`Id`int(11)NOTNULLAUTO_INCREMENT,`sid`varchar(20)DEFAULTNULL,`name`varchar(20)DEFAULTNULL,`password`varchar(20)DEFAULTNULL,`sex`varchar(20)DEFAULTNULL,`major`varchar(20)DEFAULTNULL,`hobby`varchar(20)DEFAULTNULL,PRIMARYKEY(`Id`));#添加測(cè)試數(shù)據(jù)INSERTINTO`t_user`VALUES(19,'159110909','向守超','111','男','物聯(lián)網(wǎng)工程','籃球足球'),(20,'159110901','張恒','123','男','物聯(lián)網(wǎng)工程','籃球足球');

創(chuàng)建完庫(kù)student、表t_user和添加完數(shù)據(jù)以后,在MySQL-Front圖形化界面工具中打開(kāi),其表中的數(shù)據(jù)如圖14.3所示。14.2.2設(shè)置MySQL驅(qū)動(dòng)類(lèi)Java項(xiàng)目在訪問(wèn)MySQL數(shù)據(jù)庫(kù)時(shí),需要在項(xiàng)目中設(shè)置MySQL驅(qū)動(dòng)類(lèi)路徑,即將MySQL數(shù)據(jù)庫(kù)所提供的JDBC驅(qū)動(dòng)程序(mysql-connector-java-5.1.12-bin0)導(dǎo)入到工程中。mysql-connector-java-5.1.12-bin.jar驅(qū)動(dòng)文件可在網(wǎng)絡(luò)上直接下載,當(dāng)然也可以下載其他的版本。

配置MySQL數(shù)據(jù)庫(kù)驅(qū)動(dòng)程序有兩種方法:一種方法是將驅(qū)動(dòng)程序配置到CLASSPATH中,與配置JDK的環(huán)境變量類(lèi)似,這種方法的配置將對(duì)本機(jī)中所有創(chuàng)建的項(xiàng)目起作用,但程序員一般不用這種方法;第二種方法是在基礎(chǔ)開(kāi)發(fā)工具Eclipse中選中項(xiàng)目,右鍵單擊,在彈出的快捷菜單中選擇“Properties→JavaBuildPath→libraries→AddExternalJARs…”命令,在彈出的對(duì)話框中,選擇mysql-connector-java-5.1.12-bin.jar文件。如圖14.4所示。設(shè)置MySQL驅(qū)動(dòng)類(lèi)設(shè)置MySQL驅(qū)動(dòng)類(lèi)

設(shè)置完MySQL數(shù)據(jù)庫(kù)驅(qū)動(dòng)類(lèi)路徑之后,項(xiàng)目的目錄如圖14.5所,ReferencedLibraries文件夾中的mysql-connector-java-5.1.12-bin.jar表示對(duì)該jar包的引用。14.2.2第3節(jié)part數(shù)據(jù)庫(kù)訪問(wèn)使用JDBC訪問(wèn)數(shù)據(jù)庫(kù)的步驟:●加載數(shù)據(jù)庫(kù)驅(qū)動(dòng);●建立數(shù)據(jù)連接;●創(chuàng)建Statement對(duì)象;●執(zhí)行SQL語(yǔ)句;●訪問(wèn)結(jié)果集;數(shù)據(jù)庫(kù)訪問(wèn)本節(jié)概述14.3.1加載數(shù)據(jù)庫(kù)驅(qū)動(dòng)

通常使用Class類(lèi)的forName()靜態(tài)方法來(lái)加載數(shù)據(jù)庫(kù)的驅(qū)動(dòng),其語(yǔ)法格式如下所示://加載驅(qū)動(dòng)Class.forName(數(shù)據(jù)庫(kù)驅(qū)動(dòng)類(lèi)名);

例如:Class.forName("com.mysql.jdbc.Driver");//加載MySQL驅(qū)動(dòng)

需要注意的是:不同的數(shù)據(jù)庫(kù)其數(shù)據(jù)庫(kù)驅(qū)動(dòng)類(lèi)是不同的,例如:Oracle數(shù)據(jù)庫(kù)的驅(qū)動(dòng)類(lèi)是oracle.jdbc.driver.OracleDriver,而MySQL的數(shù)據(jù)庫(kù)驅(qū)動(dòng)類(lèi)是com.mysql.jdbc.Driver。數(shù)據(jù)庫(kù)廠商在提供數(shù)據(jù)庫(kù)驅(qū)動(dòng)(通常是一個(gè)或幾個(gè)jar文件)時(shí),會(huì)有相應(yīng)的文檔說(shuō)明。加載數(shù)據(jù)庫(kù)驅(qū)動(dòng)14.3.2建立數(shù)據(jù)庫(kù)連接

在使用JDBC操作數(shù)據(jù)庫(kù)之前,需要先創(chuàng)建一個(gè)數(shù)據(jù)庫(kù)連接,使用DriverManager類(lèi)的getConnection()靜態(tài)方法來(lái)獲取數(shù)據(jù)庫(kù)連接對(duì)象,其語(yǔ)法格式如下所示:DriverManager.getConnection(Stringurl,Stringuser,Stringpass);

其中,getConnection()方法有三個(gè)參數(shù),具體如下:

●url:數(shù)據(jù)庫(kù)連接字符串,遵循的格式是“jdbc:驅(qū)動(dòng):其他”,不同的數(shù)據(jù)庫(kù)連接的URL也有所不同。

●user:連接數(shù)據(jù)庫(kù)的用戶名;

●pass:密碼。建立數(shù)據(jù)庫(kù)連接14.3.2建立數(shù)據(jù)庫(kù)連接例如,訪問(wèn)MySQL數(shù)據(jù)庫(kù)的URL連接字符串"jdbc:mysql://:3306/student"在上面的URL連接字符串中:●jdbc:mysql是協(xié)議名稱(chēng)●“”是本機(jī)服務(wù)器IP地址,也可以使用“l(fā)ocalhost”;●“3306”是MySQL數(shù)據(jù)庫(kù)的端口號(hào);●“student”是數(shù)據(jù)庫(kù)實(shí)例名。例如:獲取MySQL數(shù)據(jù)庫(kù)連接對(duì)象Class.forName("com.mysql.jdbc.Driver");Connectionconn=DriverManager.getConnection( "jdbc:mysql://:3306/student",//URL連接字符串 "root",//用戶名 "root");//密碼14.3.3創(chuàng)建Statement對(duì)象

對(duì)數(shù)據(jù)庫(kù)進(jìn)行操作或訪問(wèn)時(shí),需要使用SQL語(yǔ)句。在Java語(yǔ)言中,SQL語(yǔ)句是通過(guò)Statement對(duì)象進(jìn)行封裝后,發(fā)送給數(shù)據(jù)庫(kù)。Statement對(duì)象不是通過(guò)Statement類(lèi)直接創(chuàng)建的,而是通過(guò)Connection對(duì)象所提供的方法來(lái)創(chuàng)建各種Statement對(duì)象。

通過(guò)Connection對(duì)象來(lái)獲得Statement的方法有以下三種:

●createStatement()方法:創(chuàng)建一個(gè)基本的Statement對(duì)象;

●prepareStatement(Stringsql)方法:根據(jù)參數(shù)化的SQL語(yǔ)句創(chuàng)建一個(gè)預(yù)編譯的PreparedStatement對(duì)象;

●prepareCall(Stringsql)方法:根據(jù)SQL語(yǔ)句來(lái)創(chuàng)建一個(gè)CallableStatement對(duì)象,用于調(diào)用數(shù)據(jù)庫(kù)的存儲(chǔ)過(guò)程。

例如://創(chuàng)建Statment對(duì)象Statementstmt=conn.createStatement();創(chuàng)建Statement對(duì)象14.3.4執(zhí)行SQL語(yǔ)句

獲取Statement對(duì)象之后,就可以調(diào)用該對(duì)象的不同方法來(lái)執(zhí)行SQL語(yǔ)句。所有的Statement都有三種執(zhí)行SQL語(yǔ)句的方法,具體使用哪一種方法由SQL語(yǔ)句產(chǎn)生的結(jié)果來(lái)決定:

●executeQuery()方法:只能執(zhí)行查詢(xún)語(yǔ)句,例如SELECT語(yǔ)句,用于產(chǎn)生單個(gè)結(jié)果集;

●executeUpdate()和executeLargeUpdate()方法:用于執(zhí)行DML和DDL語(yǔ)句,執(zhí)行DML(INSERT、UPDATE或DELETE語(yǔ)句)時(shí)返回受SQL語(yǔ)句所影響的行數(shù)(整數(shù)值),而執(zhí)行DDL語(yǔ)句(CREATETABLE、DROPTABLE等)返回值總為0;●execute()方法:可以執(zhí)行任何SQL語(yǔ)句,此方法比較特殊,也比較麻煩,返回結(jié)果為多個(gè)結(jié)果集、多個(gè)更新計(jì)數(shù)或二者的組合。通常不建議使用該方法,只有在不知道執(zhí)行SQL語(yǔ)句會(huì)產(chǎn)生什么結(jié)果或可能有多種類(lèi)型結(jié)果的情況下才會(huì)使用。如果SQL語(yǔ)句運(yùn)行后能產(chǎn)生結(jié)果集,Statement對(duì)象則將結(jié)果集封裝成ResultSet對(duì)象并返回。下述代碼調(diào)用Statement對(duì)象的executeQuery()方法來(lái)執(zhí)行SQL查詢(xún)語(yǔ)句,并返回一個(gè)ResultSet結(jié)果集對(duì)象。例如:執(zhí)行SQL查詢(xún)語(yǔ)句并返回結(jié)果集ResultSetrs=smt.executeQuery("SELECT*FROMt_user");執(zhí)行SQL語(yǔ)句14.3.5訪問(wèn)結(jié)果集SQL的查詢(xún)結(jié)果使用ResultSet封裝,ResultSet結(jié)果集包含了滿足SQL查詢(xún)條件的所有的行,使用getXXX()方法對(duì)結(jié)果集中的數(shù)據(jù)進(jìn)行訪問(wèn)。

當(dāng)使用getXXX()方法訪問(wèn)結(jié)果集中的數(shù)據(jù)時(shí),可通過(guò)列索引或列名來(lái)獲取游標(biāo)所指行中的列數(shù)據(jù),其語(yǔ)法格式如下;getXXX(列索引)

或getXXX(“列名”)

例如:循環(huán)輸出結(jié)果集中第三列數(shù)據(jù)。while(rs.next()){ System.out.println(rs.getString(3));}

或while(rs.next()){ System.out.println(rs.getString("name"));}訪問(wèn)結(jié)果集訪問(wèn)結(jié)果集

需要注意的是:在使用getXXX()方法來(lái)獲得數(shù)據(jù)庫(kù)表中的對(duì)應(yīng)字段的數(shù)據(jù)時(shí),盡可能使用序列號(hào)參數(shù),這樣可以提高效率。除Blob類(lèi)型外,其他任意類(lèi)型的字段都可以通過(guò)getString()方法來(lái)獲取,因?yàn)樗袛?shù)據(jù)類(lèi)型都可以自動(dòng)轉(zhuǎn)換成字符串。

當(dāng)數(shù)據(jù)庫(kù)操作執(zhí)行完畢或退出應(yīng)用前,需將數(shù)據(jù)庫(kù)訪問(wèn)過(guò)程中建立的對(duì)象按順序關(guān)閉,防止系統(tǒng)資源浪費(fèi)。關(guān)閉的次序是:

①關(guān)閉結(jié)果集:rs.close();

②關(guān)閉Statement對(duì)象:stmt.close();

③關(guān)閉連接:conn.close();

下述案例用于示例訪問(wèn)數(shù)據(jù)庫(kù)的一般步驟,代碼如下所示。14.3.5訪問(wèn)結(jié)果集【代碼14.2】ConnectionExample.javapackagecom;importjava.sql.Connection;importjava.sql.DriverManager;importjava.sql.ResultSet;importjava.sql.SQLException;importjava.sql.Statement;publicclassConnectionExample{ publicstaticvoidmain(String[]args){ try{ //加載驅(qū)動(dòng) Class.forName("com.mysql.jdbc.Driver"); //建立數(shù)據(jù)庫(kù)連接 Connectionconn=DriverManager.getConnection( "jdbc:mysql://:3306/student","root","root"); System.out.println("連接成功!"); //創(chuàng)建Statment對(duì)象 Statementstmt=conn.createStatement(); //獲取查詢(xún)結(jié)果集 ResultSetrs=stmt.executeQuery("SELECT*FROMt_user"); 14.3.5訪問(wèn)結(jié)果集 System.out.println("查詢(xún)成功!"); //訪問(wèn)結(jié)果集中的數(shù)據(jù) while(rs.next()){ System.out.println(rs.getString(1)+"" +rs.getString("name")); } //關(guān)閉結(jié)果集 rs.close(); //關(guān)閉載體 stmt.close(); //關(guān)閉連接 conn.close(); }catch(ClassNotFoundExceptione){ e.printStackTrace(); }catch(SQLExceptione){ e.printStackTrace(); } }}14.3.5訪問(wèn)結(jié)果集

上述代碼按照訪問(wèn)數(shù)據(jù)庫(kù)的一般步驟編寫(xiě)。

①通過(guò)Class.forName()方法加載MySQL數(shù)據(jù)庫(kù)驅(qū)動(dòng);

②調(diào)用DriverManager.getConnection()方法來(lái)建立MySQL數(shù)據(jù)庫(kù)連接,在獲取連接時(shí)需要指明數(shù)據(jù)庫(kù)連接的URL、用戶名和密碼;

③通過(guò)連接對(duì)象的createStatement()方法來(lái)獲取Statement對(duì)象,調(diào)用Statement對(duì)象的executeQuery()方法執(zhí)行SQL語(yǔ)句;

④調(diào)用ResultSet結(jié)果集對(duì)象的next()方法將游標(biāo)移動(dòng)到下一條記錄,再通過(guò)getXXX()方法來(lái)獲取指定列中的數(shù)據(jù);

⑤最后調(diào)用close()方法關(guān)閉所有創(chuàng)建的對(duì)象。

程序運(yùn)行結(jié)果如下所示:

連接成功!

查詢(xún)成功!19向守超20張恒14.3.5第4節(jié)part操作數(shù)據(jù)庫(kù)JDBC不僅可以執(zhí)行數(shù)據(jù)庫(kù)查詢(xún),還可以執(zhí)行DDL、DML等SQL語(yǔ)句,以便最大限度地操作數(shù)據(jù)庫(kù)。操作數(shù)據(jù)庫(kù)本節(jié)概述14.4.1execute()方法Statement接口的execute()方法幾乎可以執(zhí)行任何SQL語(yǔ)句,如果不清楚SQL語(yǔ)句的類(lèi)型,則只能通過(guò)使用execute()方法來(lái)執(zhí)行SQL語(yǔ)句。

使用execute()方法執(zhí)行SQL語(yǔ)句的返回值是boolean值,表明執(zhí)行該SQL語(yǔ)句是否返回了ResultSet對(duì)象:

●當(dāng)返回值為true時(shí),可以使用Statement的getResultSet()方法,來(lái)獲取execute()方法執(zhí)行SQL查詢(xún)語(yǔ)句所返回的ResultSet對(duì)象;

●當(dāng)返回值為false時(shí),可以使用getUpdateCount()方法,來(lái)獲取execute()方法執(zhí)行DML語(yǔ)句所影響的行數(shù)。下述案例示例了Statement對(duì)象的execute()方法的使用,代碼如下所示。execute()方法【代碼14.3】ExecuteExample.javapackagecom;importjava.sql.Connection;importjava.sql.DriverManager;importjava.sql.ResultSet;importjava.sql.Statement;publicclassExecuteExample{ privateStringdriver="com.mysql.jdbc.Driver"; privateStringurl="jdbc:mysql://:3306/student"; privateStringuser="root"; privateStringpass="root"; publicvoidexecuteSql(Stringsql)throwsException{ //加載驅(qū)動(dòng) Class.forName(driver); try( //獲取數(shù)據(jù)庫(kù)連接 Connectionconn=DriverManager.getConnection(url,user,pass); //使用Connection來(lái)創(chuàng)建一個(gè)Statement對(duì)象 Statementstmt=conn.createStatement()){execute()方法14.4.1 //執(zhí)行SQL,返回boolean值表示是否包含ResultSet booleanhasResultSet=stmt.execute(sql); //如果執(zhí)行后有ResultSet結(jié)果集 if(hasResultSet){ try( //獲取結(jié)果集 ResultSetrs=stmt.getResultSet()){ //迭代輸出ResultSet對(duì)象 while(rs.next()){ //依次輸出第1列的值 System.out.print(rs.getString(1)+"\t"); } System.out.println(); } }else{ System.out.println("該SQL語(yǔ)句影響的記錄有" +stmt.getUpdateCount()+"條"); } } }execute()方法14.4.1 publicstaticvoidmain(String[]args)throwsException{ ExecuteExampleexecuteObj=newExecuteExample(); System.out.println("------執(zhí)行建表的DDL語(yǔ)句-----"); executeObj.executeSql("createtablemy_test"+ "(test_idintprimarykey,test_namevarchar(25))"); System.out.println("------執(zhí)行插入數(shù)據(jù)的DML語(yǔ)句-----"); executeObj.executeSql("insertintomy_test(test_id,test_name)" +"selectid,namefromt_user"); System.out.println("------執(zhí)行查詢(xún)數(shù)據(jù)的查詢(xún)語(yǔ)句-----"); executeObj.executeSql("selecttest_namefrommy_test"); System.out.println("------執(zhí)行刪除表的DDL語(yǔ)句-----"); executeObj.executeSql("droptablemy_test"); }}execute()方法14.4.1

上述代碼先定義了一個(gè)executeSql()方法,用于執(zhí)行不同的SQL語(yǔ)句,當(dāng)執(zhí)行結(jié)果有ResultSet結(jié)果集時(shí),則循環(huán)輸出結(jié)果集中第3列的信息;否則輸出該SQL語(yǔ)句所影響的記錄條數(shù)。在main()方法中,調(diào)用executeSql()方法,分別執(zhí)行建表、插入、查詢(xún)和刪除表四個(gè)SQL語(yǔ)句。程序運(yùn)行結(jié)果如下:------執(zhí)行建表的DDL語(yǔ)句-----

該SQL語(yǔ)句影響的記錄有0條------執(zhí)行插入數(shù)據(jù)的DML語(yǔ)句-----

該SQL語(yǔ)句影響的記錄有2條------執(zhí)行查詢(xún)數(shù)據(jù)的查詢(xún)語(yǔ)句-----

向守超

張恒

------執(zhí)行刪除表的DDL語(yǔ)句-----

該SQL語(yǔ)句影響的記錄有0條

需要注意的是:使用Statement執(zhí)行DDL和DML語(yǔ)句的步驟與執(zhí)行普通查詢(xún)語(yǔ)句的步驟基本相似。區(qū)別在于執(zhí)行DDL語(yǔ)句后返回值為0,而執(zhí)行了DML語(yǔ)句后返回值為受影響的行數(shù)。execute()方法14.4.114.4.2executeUpdate()方法executeUpdate()和executeLargeUpdate()方法用于執(zhí)行DDL和DML語(yǔ)句,其中executeLargeUpdate()方法是Java8新增的方法,是增強(qiáng)版的executeUpdate()方法。executeLargeUpdate()方法的返回值類(lèi)型為long,當(dāng)DML語(yǔ)句影響的記錄超過(guò)Integer.MAX_VALUE時(shí),建議使用該方法。

下述案例示例了Statement對(duì)象的executeUpdate()方法的使用,目前MySQL數(shù)據(jù)庫(kù)驅(qū)動(dòng)暫不支持executeLargeUpdate()方法功能。代碼如下所示。executeUpdate()方法executeUpdate()方法【代碼14.4】ExecuteUpdateExample.javapackagecom;importjava.sql.Connection;importjava.sql.DriverManager;importjava.sql.Statement;publicclassExecuteUpdateExample{ privateStringdriver="com.mysql.jdbc.Driver"; privateStringurl="jdbc:mysql://:3306/student"; privateStringuser="root"; privateStringpass="root"; publicvoidcreateTable(Stringsql)throwsException{ //加載驅(qū)動(dòng) Class.forName(driver); try( //獲取數(shù)據(jù)庫(kù)連接 Connectionconn=DriverManager.getConnection(url,user,pass); //使用Connection來(lái)創(chuàng)建一個(gè)Statment對(duì)象 Statementstmt=conn.createStatement()){ //執(zhí)行DDL,創(chuàng)建數(shù)據(jù)表 stmt.executeUpdate(sql); } }14.4.2executeUpdate()方法 publiclonginsertData(Stringsql)throwsException{ //加載驅(qū)動(dòng) Class.forName(driver); try( //獲取數(shù)據(jù)庫(kù)連接 Connectionconn=DriverManager.getConnection(url,user,pass); //使用Connection來(lái)創(chuàng)建一個(gè)Statment對(duì)象 Statementstmt=conn.createStatement()){ //執(zhí)行DML,返回受影響的記錄條數(shù) returnstmt.executeUpdate(sql); } }

publicstaticvoidmain(String[]args)throwsException{ ExecuteUpdateExampleelud=newExecuteUpdateExample(); elud.createTable("createtablemy_test1"+ "(test_idintprimarykey,test_namevarchar(25))"); System.out.println("-----建表成功-----"); longresult=elud.insertData( "insertintomy_test1(test_id,test_name)selectid,namefromt_user"); System.out.println("--系統(tǒng)中共有"+result+"條記錄受影響--"); }}14.4.2executeUpdate()方法

上述代碼定義了createTable()方法來(lái)創(chuàng)建表,insertData()方法用于插入數(shù)據(jù),不管是執(zhí)行DDL語(yǔ)句還是執(zhí)行DML語(yǔ)句,最終都是通過(guò)調(diào)用Statement對(duì)象的executeUpdate()方法來(lái)實(shí)現(xiàn)的。運(yùn)行該程序,結(jié)果如下所示:-----建表成功-------系統(tǒng)中共有2條記錄受影響--14.4.214.4.3PreparedStatement接口PreparedStatement接口繼承Statement接口,該接口具有以下兩個(gè)特點(diǎn):

●PreparedStatement對(duì)象中所包含的SQL語(yǔ)句將進(jìn)行預(yù)編譯,當(dāng)需要多次執(zhí)行同一條SQL語(yǔ)句時(shí),直接執(zhí)行預(yù)先編譯好的語(yǔ)句,其執(zhí)行速度比Statement對(duì)象快;

●PreparedStatement可用于執(zhí)行動(dòng)態(tài)的SQL語(yǔ)句,即在SQL語(yǔ)句中提供參數(shù),大大提高了程序的靈活性和執(zhí)行效率。

動(dòng)態(tài)SQL語(yǔ)句使用“?”作為動(dòng)態(tài)參數(shù)的占位符,示例如下所示。

例如:參數(shù)化的動(dòng)態(tài)SQL語(yǔ)句,創(chuàng)建PreparedStatement對(duì)象StringinsertSql="INSERTINTOuserdetails(sid,name,password,sex)VALUES(?,?,?,?)";PreparedStatementpstmt=conn.prepareStatement(insertSql);PreparedStatement接口PreparedStatement接口

在執(zhí)行帶參數(shù)的SQL語(yǔ)句前,必須對(duì)“?”占位符參數(shù)進(jìn)行賦值。PreparedStatement接口中提供了大量的setXXX()方法,通過(guò)占位符的索引完成對(duì)輸入?yún)?shù)的賦值,根據(jù)參數(shù)的類(lèi)型來(lái)選擇對(duì)應(yīng)的setXXX()方法,PreparedStatement接口中提供的常用setXXX()方法如表14-7所示。14.4.3PreparedStatement接口下述案例示例了PreparedStatement的使用,代碼如下所示?!敬a14.5】PreparedStatementExample.javapackagecom;importjava.sql.Connection;importjava.sql.DriverManager;importjava.sql.PreparedStatement;importjava.sql.SQLException;publicclassPreparedStatementExample{ publicstaticvoidmain(String[]args){ try{ //加載oracle驅(qū)動(dòng) Class.forName("com.mysql.jdbc.Driver"); //建立數(shù)據(jù)庫(kù)連接 Connectionconn=DriverManager.getConnection( "jdbc:mysql://:3306/student","root","root"); //定義帶參數(shù)的sql語(yǔ)句 StringinsertSql="INSERTINTOt_user(sid,name,password,sex)" +"VALUES(?,?,?,?)"; //創(chuàng)建PreparedStatement對(duì)象 PreparedStatementpstmt=conn.prepareStatement(insertSql); 14.4.3PreparedStatement接口 //使用setXXX()方法對(duì)參數(shù)賦值 pstmt.setInt(1,7); pstmt.setString(2,"Tom"); pstmt.setString(3,"123456"); pstmt.setByte(4,(byte)1); //執(zhí)行 intresult=pstmt.executeUpdate(); System.out.println("插入"+result+"行!"); //關(guān)閉載體 pstmt.close(); //關(guān)閉連接 conn.close(); }catch(ClassNotFoundExceptione){ e.printStackTrace(); }catch(SQLExceptione){ e.printStackTrace(); } }}14.4.3PreparedStatement接口

上述代碼先定義一個(gè)帶參數(shù)的SQL語(yǔ)句;再使用該語(yǔ)句來(lái)創(chuàng)建一個(gè)PreparedStatement對(duì)象;然后調(diào)用PreparedStatement對(duì)象的setXXX()方法對(duì)參數(shù)進(jìn)行賦值,并調(diào)用PreparedStatement對(duì)象的executeUpdate()方法來(lái)執(zhí)行SQL語(yǔ)句。運(yùn)行該程序,結(jié)果如下所示:

插入1行!14.4.3第5節(jié)part事務(wù)處理

事務(wù)是保證底層數(shù)據(jù)完整的重要手段,對(duì)于任何數(shù)據(jù)庫(kù)都是非常重要的。事務(wù)是由一步或幾步數(shù)據(jù)庫(kù)操作序列組成的邏輯執(zhí)行單元,這系列操作要么全部執(zhí)行,要么全部放棄執(zhí)行。事務(wù)具有ACID四個(gè)特性:

●原子性(Atomicity):事務(wù)是應(yīng)用中的最小執(zhí)行單位,就如原子是自然界的最小顆粒一樣,具有不可再分的特性。事務(wù)中的全部操作要么全部完成,要么都不執(zhí)行。

●一致性(Consistency):事務(wù)執(zhí)行之前和執(zhí)行之后,數(shù)據(jù)庫(kù)都必須處于一致性狀態(tài),即從執(zhí)行前的一個(gè)一致?tīng)顟B(tài)變?yōu)榱硪粋€(gè)一致性的狀態(tài)。

●隔離性(Isolation):各個(gè)事務(wù)的執(zhí)行互不干擾,任意一個(gè)事務(wù)的內(nèi)部操作對(duì)其他并發(fā)事務(wù)都是隔離的,即并發(fā)執(zhí)行的事務(wù)之間不能看到對(duì)方的中間狀態(tài),并發(fā)事務(wù)之間是互不影響的。

●持久性(Durability):事務(wù)一旦提交,對(duì)數(shù)據(jù)庫(kù)所做的任何改變都永久地記錄到存儲(chǔ)器中,即保存到物理數(shù)據(jù)庫(kù)中,不被丟失。事務(wù)處理事務(wù)處理

事務(wù)處理過(guò)程中會(huì)涉及到事務(wù)的提交、中止和回滾三個(gè)概念?!笆聞?wù)提交”是指成功執(zhí)行完畢事務(wù),事務(wù)提交又分顯示提交和自動(dòng)提交兩種;“事務(wù)中止”是指未能成功完成事務(wù),執(zhí)行中斷;“事務(wù)回滾”對(duì)于中止事務(wù)所造成的變更需要進(jìn)行撤銷(xiāo)處理,即事務(wù)所做的修改全部失效,數(shù)據(jù)庫(kù)返回到事務(wù)執(zhí)行前的狀態(tài),事務(wù)回滾也有顯示回滾和自動(dòng)回滾兩種。JDBC對(duì)事務(wù)操作提供了支持,其事務(wù)支持由Connection提供。JDBC的事務(wù)操作步驟如下:

①開(kāi)啟事務(wù);

②執(zhí)行任意多條DML語(yǔ)句;

③執(zhí)行成功,則提交事務(wù);

④執(zhí)行失敗,則回滾事務(wù);Connection在默認(rèn)情況下會(huì)自動(dòng)提交,即事務(wù)是關(guān)閉的。此種情況下,一條SQL語(yǔ)句更新成功后,系統(tǒng)會(huì)立即調(diào)用commit()方法提交到數(shù)據(jù)庫(kù),而無(wú)法對(duì)其進(jìn)行rollback回滾操作。事務(wù)處理

使用Connection對(duì)象的setAutoCommit()方法可開(kāi)啟或者關(guān)閉自動(dòng)提交模式,其參數(shù)是一個(gè)布爾類(lèi)型,如果參數(shù)為false,表示關(guān)閉自動(dòng)提交;如果參數(shù)

溫馨提示

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

最新文檔

評(píng)論

0/150

提交評(píng)論