




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡介
本章學(xué)習(xí)目標(biāo):●
了解JDBC概念以及驅(qū)動類型●
掌握使用JDBC連接MySQL數(shù)據(jù)庫的基本步驟●
掌握數(shù)據(jù)庫環(huán)境的搭建●
掌握使用JDBC訪問數(shù)據(jù)庫的步驟●
掌握使用JavaAPI操作數(shù)據(jù)庫●
掌握數(shù)據(jù)庫事務(wù)的使用第十四章JDBC與MySQL編程第1節(jié)partJDBC基礎(chǔ)
通過使用JDBC,Java程序可以輕松地操作各種主流數(shù)據(jù)庫,例如,Oracle、MSSQLServer、MySQL等。由于Java語言本身的跨平臺性,所以使用JDBC編寫的程序不僅可以實(shí)現(xiàn)跨數(shù)據(jù)庫,還具有跨平臺性和可移植性。使用JDBC訪問數(shù)據(jù)庫具有操作簡單、獲取方便且安全可靠等優(yōu)勢。JDBC基礎(chǔ)本節(jié)概述JDBC(JavaDatabaseConnectivity,Java數(shù)據(jù)庫連接)是一種執(zhí)行SQL語句的JavaAPI。程序可以通過JDBCAPI連接到關(guān)系數(shù)據(jù)庫,并使用SQL結(jié)構(gòu)化語言來完成對數(shù)據(jù)庫的增、刪、改、查等操作。與其他數(shù)據(jù)庫編程語言相比,JDBC為數(shù)據(jù)開發(fā)者提供了標(biāo)準(zhǔn)的API,使用JDBC開發(fā)的數(shù)據(jù)庫應(yīng)用程序可以訪問不同的數(shù)據(jù)庫,并在不同平臺上運(yùn)行,既可以在Windows平臺上運(yùn)行,也可以在UNIX平臺上運(yùn)行。JDBC程序訪問不同的數(shù)據(jù)庫時(shí),需要數(shù)據(jù)庫廠商提供相應(yīng)的驅(qū)動程序。通過JDBC驅(qū)動程序的轉(zhuǎn)換,使得相同的代碼在訪問不同的數(shù)據(jù)庫時(shí)運(yùn)行良好。JDBC驅(qū)動示意圖如圖14.1所示。14.1.1JDBC簡介JDBC簡介JDBC應(yīng)用程序可以對數(shù)據(jù)庫進(jìn)行訪問和操作,JDBC訪問數(shù)據(jù)庫時(shí)主要完成以下工作:
●建立與數(shù)據(jù)庫的連接;
●執(zhí)行SQL語句;
●獲取執(zhí)行結(jié)果。
數(shù)據(jù)庫驅(qū)動程序是JDBC程序和數(shù)據(jù)庫之間的轉(zhuǎn)換層,數(shù)據(jù)庫驅(qū)動程序負(fù)責(zé)將JDBC調(diào)用映射成特定的數(shù)據(jù)庫調(diào)用,JDBC訪問示意圖如圖14.2所示。14.1.2JDBC驅(qū)動JDBC驅(qū)動
當(dāng)今市場上主流數(shù)據(jù)庫都提供了JDBC驅(qū)動程序,甚至一些流行的數(shù)據(jù)庫還提供了多種不同版本的JDBC驅(qū)動程序。JDBC驅(qū)動程序有以下4種類型:
●JDBC-ODBC橋:是最早實(shí)現(xiàn)的JDBC驅(qū)動程序,主要目的是快速推廣JDBC。ODBC(OpenDatabaseConnectivity,開放數(shù)據(jù)庫連接)是通過一組通用的API訪問不同的數(shù)據(jù)庫管理系統(tǒng),也需要各數(shù)據(jù)庫廠商提供相應(yīng)的驅(qū)動程序,而ODBC則對這些驅(qū)動程序進(jìn)行管理。JDBC-ODBC橋驅(qū)動是將JDBCAPI映射到ODBCAPI,驅(qū)動速度很慢,只適用于訪問沒有其他JDBC驅(qū)動的數(shù)據(jù)庫。由于Java語言的廣泛應(yīng)用,所有數(shù)據(jù)庫廠商都提供了JDBC驅(qū)動,因此在Java8中不再支持JDBC-ODBC數(shù)據(jù)訪問方式。JDBC驅(qū)動14.1.2
●本地API驅(qū)動:直接將JDBCAPI映射成數(shù)據(jù)庫特定的客戶端API,包含特定的數(shù)據(jù)庫本地代碼,用于訪問特定數(shù)據(jù)庫的客戶端。本地API驅(qū)動比起JDBC-ODBC橋執(zhí)行效率要高,但是仍然需要在客戶端加載數(shù)據(jù)庫廠商提供的代碼庫,不適合基于網(wǎng)絡(luò)的應(yīng)用。本地API驅(qū)動雖然速度有所提升,但相對后面兩種JDBC驅(qū)動還是不夠高。
●網(wǎng)絡(luò)協(xié)議驅(qū)動:將JDBC調(diào)用翻譯成中間件供應(yīng)商的協(xié)議,然后再由中間件服務(wù)器翻譯成數(shù)據(jù)庫訪問協(xié)議。網(wǎng)絡(luò)協(xié)議驅(qū)動是基于服務(wù)器的,不需要在客戶端加載數(shù)據(jù)庫廠商提供的代碼庫,且執(zhí)行效率比較好,便于維護(hù)和升級。
●本地協(xié)議驅(qū)動:是純Java編寫的,可以直接連接到數(shù)據(jù)庫。本地協(xié)議驅(qū)動不需要將JDBC的調(diào)用傳給ODBC,或本地?cái)?shù)據(jù)庫接口,或中間層服務(wù)器,因此執(zhí)行效率非常高;而且根本不需要在客戶端或服務(wù)器裝載任何軟件或驅(qū)動。本地協(xié)議驅(qū)動是智能的,能夠知道數(shù)據(jù)庫使用的底層協(xié)議,是目前最流行的JDBC驅(qū)動。通常JDBC訪問數(shù)據(jù)庫時(shí)建議使用第4種本地協(xié)議驅(qū)動,該驅(qū)動使用純Java編寫,且避開了本地代碼,減少了應(yīng)用開發(fā)的復(fù)雜性,降低了產(chǎn)生沖突和出錯的可能。JDBC驅(qū)動14.1.2JDBCAPI提供了一組用于與數(shù)據(jù)庫進(jìn)行通信的接口和類,這些接口和類都定義在java.sql包中,常用的接口和類如表14-1所示。14.1.3JDBC
APIJDBC
API
需要注意的是:使用JDBCAPI中的類或接口訪問數(shù)據(jù)庫時(shí),容易引發(fā)SQLException異常,SQLException異常類是檢查型異常,需要放在try…catch語句中進(jìn)行異常處理,SQLException是JDBC中其他異常類型的基礎(chǔ)。1.DriverManager類DriverManager是數(shù)據(jù)庫驅(qū)動管理類,用于管理一組JDBC驅(qū)動程序的基本服務(wù)。應(yīng)用程序和數(shù)據(jù)庫之間可以通過DriverManager建立連接,其常用的靜態(tài)方法如表14-2所示。JDBC
API14.1.32.Connection接口Connection接口用于連接數(shù)據(jù)庫,每個Connection對象代表一個數(shù)據(jù)庫連接會話,要想訪問數(shù)據(jù)庫,必須先獲得數(shù)據(jù)庫連接。一個應(yīng)用程序可與單個數(shù)據(jù)庫建立一個或多個連接,也可以與多個數(shù)據(jù)庫建立連接。通過DriverManager類的getConnection()方法可以返回一個Connection對象,該對象中提供了創(chuàng)建SQL語句的方法,以完成基本的SQL操作,同時(shí)為數(shù)據(jù)庫事務(wù)提供了提交和回滾的方法。Connection接口中常用的方法如表14-3所示。JDBC
API14.1.33.Statement接口Statement接口一般用于執(zhí)行SQL語句。在JDBC中要執(zhí)行SQL查詢語句的方式有一般查詢(Statement)、參數(shù)查詢(PreparedStatement)和存儲過程(CallableStatement)三種方式。Connection接口中提供的createStatement()、prepareStatement()和prepareCall()方法分別返回一個Statement對象,PreparedStatement對象和CallableStatement對象。Statement、PreparedStatement和CallableStatement三個接口具有繼承關(guān)系,其中PreparedStatement是Statement的子接口,而CallableStatement又是PreparedStatement的子接口。Statement接口的主要功能是將SQL語句傳送給數(shù)據(jù)庫,并返回SQL語句的執(zhí)行結(jié)果。Statement提交的SQL語句是靜態(tài)的,不需要接收任何參數(shù),SQL語句可以包含以下三種類型的語句:
●SELECT查詢語句;
●DML語句,如INSERT、UPDATE或DELETE;
●DDL語句,如CREATETABLE和DROPTABLE。JDBC
API14.1.3Statement接口中常用的方法及功能如表14-4所示。JDBC
API
需要注意的是:closeOnCompletion()和isCloseOnCompletion()方法是從Java7開始新增的方法,executeLargeUpdate()方法是從Java8開始新增的方法,在開發(fā)過程中使用這幾個方法時(shí)需要注意JDK的版本。考慮到目前應(yīng)用程序所處理的數(shù)據(jù)量越來越大,使用executeLargeUpdate()方法具有更好的適應(yīng)性,但目前有的數(shù)據(jù)庫驅(qū)動暫不支持該方法,例如MySQL驅(qū)動。14.1.34.ResultSet接口ResultSet接口用于封裝結(jié)果集對象,該對象包含訪問查詢結(jié)果的方法。使用Statement中的executeQuery()方法可以返回一個ResultSet結(jié)果集的對象,該對象封裝了所有符合查詢條件的記錄。ResultSet具有指向當(dāng)前數(shù)據(jù)行的游標(biāo),并提供了許多方法來操作結(jié)果集中的游標(biāo),同時(shí)還提供了一套getXXX()方法對結(jié)果集中的數(shù)據(jù)進(jìn)行訪問,這些方法可以通過列索引或列名獲得數(shù)據(jù)。ResultSet接口中常用的方法如表14-5所示。JDBC
API14.1.3ResultSet對象具有指向當(dāng)前數(shù)據(jù)行的游標(biāo)。最初游標(biāo)位于第一行之前,每調(diào)用一次next()方法,游標(biāo)會自動向下移一行,從而可以從上到下依次獲取所有數(shù)據(jù)行。getXXX()方法用于對游標(biāo)所指向的行的數(shù)據(jù)進(jìn)行訪問。在使用getXXX()方法取值時(shí),數(shù)據(jù)庫的字段數(shù)據(jù)類型要與Java的數(shù)據(jù)類型相匹配,例如,數(shù)據(jù)庫中的整數(shù)字段對應(yīng)Java數(shù)據(jù)類型中的int類型,此時(shí)使用getInt()方法來讀取該字段中的數(shù)據(jù)。常用的SQL數(shù)據(jù)類型和Java數(shù)據(jù)類型之間的對應(yīng)關(guān)系如表14-6所示。JDBC
API14.1.3第2節(jié)part數(shù)據(jù)庫環(huán)境搭建14.2.1創(chuàng)建數(shù)據(jù)庫表
本章JDBC數(shù)據(jù)庫訪問基于MySQL數(shù)據(jù)庫,因此所有的代碼及環(huán)境都是基于MySQL數(shù)據(jù)庫的。在進(jìn)行數(shù)據(jù)庫訪問操作之前,需要先創(chuàng)建數(shù)據(jù)庫和表并錄入測試數(shù)據(jù)。在root用戶下創(chuàng)建student數(shù)據(jù)庫,并在該庫下創(chuàng)建t_user表,并添加測試數(shù)據(jù),其SQL代碼如下所示。創(chuàng)建數(shù)據(jù)庫表創(chuàng)建數(shù)據(jù)庫表
【代碼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`));#添加測試數(shù)據(jù)INSERTINTO`t_user`VALUES(19,'159110909','向守超','111','男','物聯(lián)網(wǎng)工程','籃球足球'),(20,'159110901','張恒','123','男','物聯(lián)網(wǎng)工程','籃球足球');
創(chuàng)建完庫student、表t_user和添加完數(shù)據(jù)以后,在MySQL-Front圖形化界面工具中打開,其表中的數(shù)據(jù)如圖14.3所示。14.2.2設(shè)置MySQL驅(qū)動類Java項(xiàng)目在訪問MySQL數(shù)據(jù)庫時(shí),需要在項(xiàng)目中設(shè)置MySQL驅(qū)動類路徑,即將MySQL數(shù)據(jù)庫所提供的JDBC驅(qū)動程序(mysql-connector-java-5.1.12-bin0)導(dǎo)入到工程中。mysql-connector-java-5.1.12-bin.jar驅(qū)動文件可在網(wǎng)絡(luò)上直接下載,當(dāng)然也可以下載其他的版本。
配置MySQL數(shù)據(jù)庫驅(qū)動程序有兩種方法:一種方法是將驅(qū)動程序配置到CLASSPATH中,與配置JDK的環(huán)境變量類似,這種方法的配置將對本機(jī)中所有創(chuàng)建的項(xiàng)目起作用,但程序員一般不用這種方法;第二種方法是在基礎(chǔ)開發(fā)工具Eclipse中選中項(xiàng)目,右鍵單擊,在彈出的快捷菜單中選擇“Properties→JavaBuildPath→libraries→AddExternalJARs…”命令,在彈出的對話框中,選擇mysql-connector-java-5.1.12-bin.jar文件。如圖14.4所示。設(shè)置MySQL驅(qū)動類設(shè)置MySQL驅(qū)動類
設(shè)置完MySQL數(shù)據(jù)庫驅(qū)動類路徑之后,項(xiàng)目的目錄如圖14.5所,ReferencedLibraries文件夾中的mysql-connector-java-5.1.12-bin.jar表示對該jar包的引用。14.2.2第3節(jié)part數(shù)據(jù)庫訪問使用JDBC訪問數(shù)據(jù)庫的步驟:●加載數(shù)據(jù)庫驅(qū)動;●建立數(shù)據(jù)連接;●創(chuàng)建Statement對象;●執(zhí)行SQL語句;●訪問結(jié)果集;數(shù)據(jù)庫訪問本節(jié)概述14.3.1加載數(shù)據(jù)庫驅(qū)動
通常使用Class類的forName()靜態(tài)方法來加載數(shù)據(jù)庫的驅(qū)動,其語法格式如下所示://加載驅(qū)動Class.forName(數(shù)據(jù)庫驅(qū)動類名);
例如:Class.forName("com.mysql.jdbc.Driver");//加載MySQL驅(qū)動
需要注意的是:不同的數(shù)據(jù)庫其數(shù)據(jù)庫驅(qū)動類是不同的,例如:Oracle數(shù)據(jù)庫的驅(qū)動類是oracle.jdbc.driver.OracleDriver,而MySQL的數(shù)據(jù)庫驅(qū)動類是com.mysql.jdbc.Driver。數(shù)據(jù)庫廠商在提供數(shù)據(jù)庫驅(qū)動(通常是一個或幾個jar文件)時(shí),會有相應(yīng)的文檔說明。加載數(shù)據(jù)庫驅(qū)動14.3.2建立數(shù)據(jù)庫連接
在使用JDBC操作數(shù)據(jù)庫之前,需要先創(chuàng)建一個數(shù)據(jù)庫連接,使用DriverManager類的getConnection()靜態(tài)方法來獲取數(shù)據(jù)庫連接對象,其語法格式如下所示:DriverManager.getConnection(Stringurl,Stringuser,Stringpass);
其中,getConnection()方法有三個參數(shù),具體如下:
●url:數(shù)據(jù)庫連接字符串,遵循的格式是“jdbc:驅(qū)動:其他”,不同的數(shù)據(jù)庫連接的URL也有所不同。
●user:連接數(shù)據(jù)庫的用戶名;
●pass:密碼。建立數(shù)據(jù)庫連接14.3.2建立數(shù)據(jù)庫連接例如,訪問MySQL數(shù)據(jù)庫的URL連接字符串"jdbc:mysql://:3306/student"在上面的URL連接字符串中:●jdbc:mysql是協(xié)議名稱●“”是本機(jī)服務(wù)器IP地址,也可以使用“l(fā)ocalhost”;●“3306”是MySQL數(shù)據(jù)庫的端口號;●“student”是數(shù)據(jù)庫實(shí)例名。例如:獲取MySQL數(shù)據(jù)庫連接對象Class.forName("com.mysql.jdbc.Driver");Connectionconn=DriverManager.getConnection( "jdbc:mysql://:3306/student",//URL連接字符串 "root",//用戶名 "root");//密碼14.3.3創(chuàng)建Statement對象
對數(shù)據(jù)庫進(jìn)行操作或訪問時(shí),需要使用SQL語句。在Java語言中,SQL語句是通過Statement對象進(jìn)行封裝后,發(fā)送給數(shù)據(jù)庫。Statement對象不是通過Statement類直接創(chuàng)建的,而是通過Connection對象所提供的方法來創(chuàng)建各種Statement對象。
通過Connection對象來獲得Statement的方法有以下三種:
●createStatement()方法:創(chuàng)建一個基本的Statement對象;
●prepareStatement(Stringsql)方法:根據(jù)參數(shù)化的SQL語句創(chuàng)建一個預(yù)編譯的PreparedStatement對象;
●prepareCall(Stringsql)方法:根據(jù)SQL語句來創(chuàng)建一個CallableStatement對象,用于調(diào)用數(shù)據(jù)庫的存儲過程。
例如://創(chuàng)建Statment對象Statementstmt=conn.createStatement();創(chuàng)建Statement對象14.3.4執(zhí)行SQL語句
獲取Statement對象之后,就可以調(diào)用該對象的不同方法來執(zhí)行SQL語句。所有的Statement都有三種執(zhí)行SQL語句的方法,具體使用哪一種方法由SQL語句產(chǎn)生的結(jié)果來決定:
●executeQuery()方法:只能執(zhí)行查詢語句,例如SELECT語句,用于產(chǎn)生單個結(jié)果集;
●executeUpdate()和executeLargeUpdate()方法:用于執(zhí)行DML和DDL語句,執(zhí)行DML(INSERT、UPDATE或DELETE語句)時(shí)返回受SQL語句所影響的行數(shù)(整數(shù)值),而執(zhí)行DDL語句(CREATETABLE、DROPTABLE等)返回值總為0;●execute()方法:可以執(zhí)行任何SQL語句,此方法比較特殊,也比較麻煩,返回結(jié)果為多個結(jié)果集、多個更新計(jì)數(shù)或二者的組合。通常不建議使用該方法,只有在不知道執(zhí)行SQL語句會產(chǎn)生什么結(jié)果或可能有多種類型結(jié)果的情況下才會使用。如果SQL語句運(yùn)行后能產(chǎn)生結(jié)果集,Statement對象則將結(jié)果集封裝成ResultSet對象并返回。下述代碼調(diào)用Statement對象的executeQuery()方法來執(zhí)行SQL查詢語句,并返回一個ResultSet結(jié)果集對象。例如:執(zhí)行SQL查詢語句并返回結(jié)果集ResultSetrs=smt.executeQuery("SELECT*FROMt_user");執(zhí)行SQL語句14.3.5訪問結(jié)果集SQL的查詢結(jié)果使用ResultSet封裝,ResultSet結(jié)果集包含了滿足SQL查詢條件的所有的行,使用getXXX()方法對結(jié)果集中的數(shù)據(jù)進(jìn)行訪問。
當(dāng)使用getXXX()方法訪問結(jié)果集中的數(shù)據(jù)時(shí),可通過列索引或列名來獲取游標(biāo)所指行中的列數(shù)據(jù),其語法格式如下;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"));}訪問結(jié)果集訪問結(jié)果集
需要注意的是:在使用getXXX()方法來獲得數(shù)據(jù)庫表中的對應(yīng)字段的數(shù)據(jù)時(shí),盡可能使用序列號參數(shù),這樣可以提高效率。除Blob類型外,其他任意類型的字段都可以通過getString()方法來獲取,因?yàn)樗袛?shù)據(jù)類型都可以自動轉(zhuǎn)換成字符串。
當(dāng)數(shù)據(jù)庫操作執(zhí)行完畢或退出應(yīng)用前,需將數(shù)據(jù)庫訪問過程中建立的對象按順序關(guān)閉,防止系統(tǒng)資源浪費(fèi)。關(guān)閉的次序是:
①關(guān)閉結(jié)果集:rs.close();
②關(guān)閉Statement對象:stmt.close();
③關(guān)閉連接:conn.close();
下述案例用于示例訪問數(shù)據(jù)庫的一般步驟,代碼如下所示。14.3.5訪問結(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ū)動 Class.forName("com.mysql.jdbc.Driver"); //建立數(shù)據(jù)庫連接 Connectionconn=DriverManager.getConnection( "jdbc:mysql://:3306/student","root","root"); System.out.println("連接成功!"); //創(chuàng)建Statment對象 Statementstmt=conn.createStatement(); //獲取查詢結(jié)果集 ResultSetrs=stmt.executeQuery("SELECT*FROMt_user"); 14.3.5訪問結(jié)果集 System.out.println("查詢成功!"); //訪問結(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訪問結(jié)果集
上述代碼按照訪問數(shù)據(jù)庫的一般步驟編寫。
①通過Class.forName()方法加載MySQL數(shù)據(jù)庫驅(qū)動;
②調(diào)用DriverManager.getConnection()方法來建立MySQL數(shù)據(jù)庫連接,在獲取連接時(shí)需要指明數(shù)據(jù)庫連接的URL、用戶名和密碼;
③通過連接對象的createStatement()方法來獲取Statement對象,調(diào)用Statement對象的executeQuery()方法執(zhí)行SQL語句;
④調(diào)用ResultSet結(jié)果集對象的next()方法將游標(biāo)移動到下一條記錄,再通過getXXX()方法來獲取指定列中的數(shù)據(jù);
⑤最后調(diào)用close()方法關(guān)閉所有創(chuàng)建的對象。
程序運(yùn)行結(jié)果如下所示:
連接成功!
查詢成功!19向守超20張恒14.3.5第4節(jié)part操作數(shù)據(jù)庫JDBC不僅可以執(zhí)行數(shù)據(jù)庫查詢,還可以執(zhí)行DDL、DML等SQL語句,以便最大限度地操作數(shù)據(jù)庫。操作數(shù)據(jù)庫本節(jié)概述14.4.1execute()方法Statement接口的execute()方法幾乎可以執(zhí)行任何SQL語句,如果不清楚SQL語句的類型,則只能通過使用execute()方法來執(zhí)行SQL語句。
使用execute()方法執(zhí)行SQL語句的返回值是boolean值,表明執(zhí)行該SQL語句是否返回了ResultSet對象:
●當(dāng)返回值為true時(shí),可以使用Statement的getResultSet()方法,來獲取execute()方法執(zhí)行SQL查詢語句所返回的ResultSet對象;
●當(dāng)返回值為false時(shí),可以使用getUpdateCount()方法,來獲取execute()方法執(zhí)行DML語句所影響的行數(shù)。下述案例示例了Statement對象的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ū)動 Class.forName(driver); try( //獲取數(shù)據(jù)庫連接 Connectionconn=DriverManager.getConnection(url,user,pass); //使用Connection來創(chuàng)建一個Statement對象 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對象 while(rs.next()){ //依次輸出第1列的值 System.out.print(rs.getString(1)+"\t"); } System.out.println(); } }else{ System.out.println("該SQL語句影響的記錄有" +stmt.getUpdateCount()+"條"); } } }execute()方法14.4.1 publicstaticvoidmain(String[]args)throwsException{ ExecuteExampleexecuteObj=newExecuteExample(); System.out.println("------執(zhí)行建表的DDL語句-----"); executeObj.executeSql("createtablemy_test"+ "(test_idintprimarykey,test_namevarchar(25))"); System.out.println("------執(zhí)行插入數(shù)據(jù)的DML語句-----"); executeObj.executeSql("insertintomy_test(test_id,test_name)" +"selectid,namefromt_user"); System.out.println("------執(zhí)行查詢數(shù)據(jù)的查詢語句-----"); executeObj.executeSql("selecttest_namefrommy_test"); System.out.println("------執(zhí)行刪除表的DDL語句-----"); executeObj.executeSql("droptablemy_test"); }}execute()方法14.4.1
上述代碼先定義了一個executeSql()方法,用于執(zhí)行不同的SQL語句,當(dāng)執(zhí)行結(jié)果有ResultSet結(jié)果集時(shí),則循環(huán)輸出結(jié)果集中第3列的信息;否則輸出該SQL語句所影響的記錄條數(shù)。在main()方法中,調(diào)用executeSql()方法,分別執(zhí)行建表、插入、查詢和刪除表四個SQL語句。程序運(yùn)行結(jié)果如下:------執(zhí)行建表的DDL語句-----
該SQL語句影響的記錄有0條------執(zhí)行插入數(shù)據(jù)的DML語句-----
該SQL語句影響的記錄有2條------執(zhí)行查詢數(shù)據(jù)的查詢語句-----
向守超
張恒
------執(zhí)行刪除表的DDL語句-----
該SQL語句影響的記錄有0條
需要注意的是:使用Statement執(zhí)行DDL和DML語句的步驟與執(zhí)行普通查詢語句的步驟基本相似。區(qū)別在于執(zhí)行DDL語句后返回值為0,而執(zhí)行了DML語句后返回值為受影響的行數(shù)。execute()方法14.4.114.4.2executeUpdate()方法executeUpdate()和executeLargeUpdate()方法用于執(zhí)行DDL和DML語句,其中executeLargeUpdate()方法是Java8新增的方法,是增強(qiáng)版的executeUpdate()方法。executeLargeUpdate()方法的返回值類型為long,當(dāng)DML語句影響的記錄超過Integer.MAX_VALUE時(shí),建議使用該方法。
下述案例示例了Statement對象的executeUpdate()方法的使用,目前MySQL數(shù)據(jù)庫驅(qū)動暫不支持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ū)動 Class.forName(driver); try( //獲取數(shù)據(jù)庫連接 Connectionconn=DriverManager.getConnection(url,user,pass); //使用Connection來創(chuàng)建一個Statment對象 Statementstmt=conn.createStatement()){ //執(zhí)行DDL,創(chuàng)建數(shù)據(jù)表 stmt.executeUpdate(sql); } }14.4.2executeUpdate()方法 publiclonginsertData(Stringsql)throwsException{ //加載驅(qū)動 Class.forName(driver); try( //獲取數(shù)據(jù)庫連接 Connectionconn=DriverManager.getConnection(url,user,pass); //使用Connection來創(chuàng)建一個Statment對象 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()方法來創(chuàng)建表,insertData()方法用于插入數(shù)據(jù),不管是執(zhí)行DDL語句還是執(zhí)行DML語句,最終都是通過調(diào)用Statement對象的executeUpdate()方法來實(shí)現(xiàn)的。運(yùn)行該程序,結(jié)果如下所示:-----建表成功-------系統(tǒng)中共有2條記錄受影響--14.4.214.4.3PreparedStatement接口PreparedStatement接口繼承Statement接口,該接口具有以下兩個特點(diǎn):
●PreparedStatement對象中所包含的SQL語句將進(jìn)行預(yù)編譯,當(dāng)需要多次執(zhí)行同一條SQL語句時(shí),直接執(zhí)行預(yù)先編譯好的語句,其執(zhí)行速度比Statement對象快;
●PreparedStatement可用于執(zhí)行動態(tài)的SQL語句,即在SQL語句中提供參數(shù),大大提高了程序的靈活性和執(zhí)行效率。
動態(tài)SQL語句使用“?”作為動態(tài)參數(shù)的占位符,示例如下所示。
例如:參數(shù)化的動態(tài)SQL語句,創(chuàng)建PreparedStatement對象StringinsertSql="INSERTINTOuserdetails(sid,name,password,sex)VALUES(?,?,?,?)";PreparedStatementpstmt=conn.prepareStatement(insertSql);PreparedStatement接口PreparedStatement接口
在執(zhí)行帶參數(shù)的SQL語句前,必須對“?”占位符參數(shù)進(jìn)行賦值。PreparedStatement接口中提供了大量的setXXX()方法,通過占位符的索引完成對輸入?yún)?shù)的賦值,根據(jù)參數(shù)的類型來選擇對應(yīng)的setXXX()方法,PreparedStatement接口中提供的常用setXXX()方法如表14-7所示。14.4.3PreparedStatement接口下述案例示例了PreparedStatement的使用,代碼如下所示。【代碼14.5】PreparedStatementExample.javapackagecom;importjava.sql.Connection;importjava.sql.DriverManager;importjava.sql.PreparedStatement;importjava.sql.SQLException;publicclassPreparedStatementExample{ publicstaticvoidmain(String[]args){ try{ //加載oracle驅(qū)動 Class.forName("com.mysql.jdbc.Driver"); //建立數(shù)據(jù)庫連接 Connectionconn=DriverManager.getConnection( "jdbc:mysql://:3306/student","root","root"); //定義帶參數(shù)的sql語句 StringinsertSql="INSERTINTOt_user(sid,name,password,sex)" +"VALUES(?,?,?,?)"; //創(chuàng)建PreparedStatement對象 PreparedStatementpstmt=conn.prepareStatement(insertSql); 14.4.3PreparedStatement接口 //使用setXXX()方法對參數(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接口
上述代碼先定義一個帶參數(shù)的SQL語句;再使用該語句來創(chuàng)建一個PreparedStatement對象;然后調(diào)用PreparedStatement對象的setXXX()方法對參數(shù)進(jìn)行賦值,并調(diào)用PreparedStatement對象的executeUpdate()方法來執(zhí)行SQL語句。運(yùn)行該程序,結(jié)果如下所示:
插入1行!14.4.3第5節(jié)part事務(wù)處理
事務(wù)是保證底層數(shù)據(jù)完整的重要手段,對于任何數(shù)據(jù)庫都是非常重要的。事務(wù)是由一步或幾步數(shù)據(jù)庫操作序列組成的邏輯執(zhí)行單元,這系列操作要么全部執(zhí)行,要么全部放棄執(zhí)行。事務(wù)具有ACID四個特性:
●原子性(Atomicity):事務(wù)是應(yīng)用中的最小執(zhí)行單位,就如原子是自然界的最小顆粒一樣,具有不可再分的特性。事務(wù)中的全部操作要么全部完成,要么都不執(zhí)行。
●一致性(Consistency):事務(wù)執(zhí)行之前和執(zhí)行之后,數(shù)據(jù)庫都必須處于一致性狀態(tài),即從執(zhí)行前的一個一致狀態(tài)變?yōu)榱硪粋€一致性的狀態(tài)。
●隔離性(Isolation):各個事務(wù)的執(zhí)行互不干擾,任意一個事務(wù)的內(nèi)部操作對其他并發(fā)事務(wù)都是隔離的,即并發(fā)執(zhí)行的事務(wù)之間不能看到對方的中間狀態(tài),并發(fā)事務(wù)之間是互不影響的。
●持久性(Durability):事務(wù)一旦提交,對數(shù)據(jù)庫所做的任何改變都永久地記錄到存儲器中,即保存到物理數(shù)據(jù)庫中,不被丟失。事務(wù)處理事務(wù)處理
事務(wù)處理過程中會涉及到事務(wù)的提交、中止和回滾三個概念。“事務(wù)提交”是指成功執(zhí)行完畢事務(wù),事務(wù)提交又分顯示提交和自動提交兩種;“事務(wù)中止”是指未能成功完成事務(wù),執(zhí)行中斷;“事務(wù)回滾”對于中止事務(wù)所造成的變更需要進(jìn)行撤銷處理,即事務(wù)所做的修改全部失效,數(shù)據(jù)庫返回到事務(wù)執(zhí)行前的狀態(tài),事務(wù)回滾也有顯示回滾和自動回滾兩種。JDBC對事務(wù)操作提供了支持,其事務(wù)支持由Connection提供。JDBC的事務(wù)操作步驟如下:
①開啟事務(wù);
②執(zhí)行任意多條DML語句;
③執(zhí)行成功,則提交事務(wù);
④執(zhí)行失敗,則回滾事務(wù);Connection在默認(rèn)情況下會自動提交,即事務(wù)是關(guān)閉的。此種情況下,一條SQL語句更新成功后,系統(tǒng)會立即調(diào)用commit()方法提交到數(shù)據(jù)庫,而無法對其進(jìn)行rollback回滾操作。事務(wù)處理
使用Connection對象的setAutoCommit()方法可開啟或者關(guān)閉自動提交模式,其參數(shù)是一個布爾類型,如果參數(shù)為false,表示關(guān)閉自動提交;如果參數(shù)
溫馨提示
- 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)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 高溫歷程對沙漠砂混凝土力學(xué)性能劣化影響研究
- K銀行寧夏分行基層管理人員勝任力模型研究
- 編程興趣小組線上學(xué)習(xí)計(jì)劃
- 射頻濾波放大電路的一體化融合設(shè)計(jì)
- 信息技術(shù)支持農(nóng)業(yè)種植合作框架協(xié)議
- 2025年秋季學(xué)期園藝實(shí)踐活動計(jì)劃
- 小學(xué)道德與法治學(xué)習(xí)評價(jià)計(jì)劃
- 2025年小學(xué)語文畢業(yè)升學(xué)考試模擬試卷:趣味知識拓展與文學(xué)常識問答
- 2025年鄉(xiāng)村醫(yī)生考試題庫:農(nóng)村急救技能操作急救技能評估歷年真題解析模擬測試卷庫
- 環(huán)保工程實(shí)施成本控制措施
- 《電氣控制系統(tǒng)設(shè)計(jì)與裝調(diào)》教案 項(xiàng)目六 任務(wù)二:順序啟動同時(shí)停止線路設(shè)計(jì)與安裝調(diào)試
- DB43T 1491-2018 貴鉛中砷、鉍、銅和銻量的測定 電感耦合等離子體發(fā)射光譜法
- 聲樂課課件教學(xué)
- 保密法實(shí)施條例培訓(xùn)
- 泰山產(chǎn)業(yè)領(lǐng)軍人才申報(bào)書
- 《沿海灘涂鹽堿地機(jī)插水稻高產(chǎn)栽培技術(shù)規(guī)程(報(bào)批稿)》編制說明
- GB/T 44395-2024激光雷達(dá)測風(fēng)數(shù)據(jù)可靠性評價(jià)技術(shù)規(guī)范
- 2024年四川成都市成華區(qū)“蓉漂人才薈”事業(yè)單位招聘高層次人才歷年高頻500題難、易錯點(diǎn)模擬試題附帶答案詳解
- 衛(wèi)浴產(chǎn)品經(jīng)銷合同模板
- 2024年浙江省金華市東陽市橫店鎮(zhèn)三校中考二模道德與法治試題(原卷版)
- 人教版(2024新版)九年級上冊化學(xué):第四單元 跨學(xué)科實(shí)踐活動3《水質(zhì)檢測及自制凈水器》教案教學(xué)設(shè)計(jì)
評論
0/150
提交評論