第2章 JDBC數(shù)據(jù)庫編程_第1頁
第2章 JDBC數(shù)據(jù)庫編程_第2頁
第2章 JDBC數(shù)據(jù)庫編程_第3頁
第2章 JDBC數(shù)據(jù)庫編程_第4頁
第2章 JDBC數(shù)據(jù)庫編程_第5頁
已閱讀5頁,還剩78頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡介

第2章JDBC數(shù)據(jù)庫編程1.1JDBC概述1.2數(shù)據(jù)庫基本操作1.3數(shù)據(jù)庫存取優(yōu)化習(xí)題

2.1JDBC概述2.1.1JDBC數(shù)據(jù)庫應(yīng)用模型

JDBC由兩層構(gòu)成,一層是JDBCAPI,負(fù)責(zé)在Java應(yīng)用程序與JDBC驅(qū)動程序管理器之間進(jìn)行通信,負(fù)責(zé)發(fā)送程序中的SQL語句。其下一層是JDBC驅(qū)動程序API,與實(shí)際連接數(shù)據(jù)庫的第三方驅(qū)動程序進(jìn)行通信,返回查詢信息或者執(zhí)行規(guī)定的操作。如圖所示。

1.Java應(yīng)用程序

Java程序包括應(yīng)用程序、Applet以及Servlet,這些類型的程序都可以利用JDBC實(shí)現(xiàn)對數(shù)據(jù)庫的訪問,JDBC在其中所起的作用包括:請求與數(shù)據(jù)庫建立連接、向數(shù)據(jù)庫發(fā)送SQL請求、處理查詢、錯(cuò)誤處理等操作。

2.JDBC驅(qū)動程序管理器

JDBC驅(qū)動程序管理器動態(tài)地管理和維護(hù)數(shù)據(jù)庫查詢所需要的驅(qū)動程序?qū)ο螅瑢?shí)現(xiàn)Java程序與特定驅(qū)動程序的連接。它完成的主要任務(wù)包括:為特定的數(shù)據(jù)庫選取驅(qū)動程序、處理JDBC初始化調(diào)用、為每個(gè)驅(qū)動程序提供JDBC功能的入口、為JDBC調(diào)用傳遞參數(shù)等。3.驅(qū)動程序驅(qū)動程序一般由數(shù)據(jù)庫廠商或者第三方提供,由JDBC方法調(diào)用,向特定數(shù)據(jù)庫發(fā)送SQL請求,并為程序獲取結(jié)果。驅(qū)動程序完成下列的任務(wù):建立與數(shù)據(jù)庫的連接、向數(shù)據(jù)庫發(fā)送請求、在用戶程序請求時(shí)進(jìn)行翻譯、錯(cuò)誤處理。4.?dāng)?shù)據(jù)庫數(shù)據(jù)庫指數(shù)據(jù)庫管理系統(tǒng)和用戶程序所需要的數(shù)據(jù)庫。2.1.2JDBC驅(qū)動程序JDBC驅(qū)動程序分為以下四種類型。(1)類型1,JDBC-ODBCBridgeDriver,這種驅(qū)動方式通過ODBC驅(qū)動器提供數(shù)據(jù)庫連接。使用這種方式要求客戶機(jī)裝入ODBC驅(qū)動程序。(2)類型2,Native-APIpartly-JavaDriver,這種驅(qū)動方式將數(shù)據(jù)庫廠商所提供的特殊協(xié)議轉(zhuǎn)換為Java代碼及二進(jìn)制代碼,利用客戶機(jī)上的本地代碼庫與數(shù)據(jù)庫進(jìn)行直接通信。和類型1一樣,這種驅(qū)動方式也存在很多局限,由于使用本地庫,因此,必須將這些庫預(yù)先安裝在客戶機(jī)上。(3)類型3,JDBC-NetAll-JavaDriver,這種類型的驅(qū)動程序是純Java代碼的驅(qū)動程序,它將JDBC指令轉(zhuǎn)換成獨(dú)立于DBMS的網(wǎng)絡(luò)協(xié)議形式并與某種中間層連接,再通過中間層與特定的數(shù)據(jù)庫通信。該類型驅(qū)動具有最大的靈活性,通常由非數(shù)據(jù)庫廠商提供,是四種類型中最小的。(4)類型4,Native-protocolAll-JavaDriver,這種驅(qū)動程序也是一種純Java的驅(qū)動程序,它通過本地協(xié)議直接與數(shù)據(jù)庫引擎相連接。這種驅(qū)動程序也能應(yīng)用于Internet。在全部四種驅(qū)動方式中,這種方式具有最好的性能。2.1.3用JDBC訪問數(shù)據(jù)庫用JDBC實(shí)現(xiàn)訪問數(shù)據(jù)庫要經(jīng)歷以下幾個(gè)步驟:1.建立數(shù)據(jù)源這里的數(shù)據(jù)源是指ODBC數(shù)據(jù)源,這一點(diǎn)不是JDBC所必需的,而是當(dāng)使用驅(qū)動程序類型1即JDBC-ODBCBridge建立連接時(shí)所需要的步驟。2.裝入JDBC驅(qū)動程序

DriverManager類管理各種數(shù)據(jù)庫驅(qū)動程序,建立新的數(shù)據(jù)庫連接。

JDBC驅(qū)動程序通過調(diào)用registerDriver方法進(jìn)行注冊。用戶在正常情況下不會直接調(diào)用DriverManager.registerDriver,而是在加載驅(qū)動程序時(shí)由驅(qū)動程序自動調(diào)用。加載Driver類,自動在DriverManager中注冊的方法有以下兩種:(1)調(diào)用方法Class.forName()將顯式地加載驅(qū)動程序類。例如加載Sybase數(shù)據(jù)庫驅(qū)動程序:

Class.forName(“com.sybase.jdbc2.jdbc.SybDriver”);(2)通過將驅(qū)動程序添加到j(luò)ava.lang.System的屬性jdbc.drivers中。初始化DriverManager類時(shí),它自動搜索系統(tǒng)屬性jdbc.drvers且加載其中包含的一個(gè)或多個(gè)驅(qū)動程序。例如下面的代碼準(zhǔn)備加載三個(gè)驅(qū)動程序類:

jdbc.drivers=ei.bar.Driver:bee.sql.Driver:see.test.ourDriver;3.建立連接與數(shù)據(jù)庫建立連接的方法包括:

DriverManager.getConnection(String

url)

DriverManager.getConnection(String

url,Propertiespro)

DriverManager.getConnection(String

url,String

user,Stringpassword)

其中,url指出使用哪個(gè)驅(qū)動程序以及連接數(shù)據(jù)庫所需的其它信息。其格式為:

jdbc:<subprotocol>:<subname>例如:

Stringurl=“jdbc:microsoft:sqlserver://localhost:1433;User=JavaDB;Password=javadb;DatabaseName=northwind”;這里,subprotocol為microsoft,而subname為sqlserver及其后的內(nèi)容。至于用戶名和口令也是存取數(shù)據(jù)所需的信息。有時(shí)候,可以采用另一種方式建立連接:

Stringurl=“jdbc:microsoft:sqlserver://localhost:1433;DatabaseName=northwind”;

Connectioncon=DriverManager.getConnection(url,”JavaDB”,”javadb”);4.執(zhí)行SQL語句與數(shù)據(jù)庫建立連接之后,需要向訪問的數(shù)據(jù)庫發(fā)送SQL語句。在特定的程序環(huán)境和功能需求下,可能需要不同的SQL語句,例如數(shù)據(jù)庫的增刪改查等操作,或者數(shù)據(jù)庫或表的創(chuàng)建及維護(hù)操作等等。需要說明的是:Java程序中所用到的SQL語句是否能得到正確的執(zhí)行,是否會產(chǎn)生異常或錯(cuò)誤,需要關(guān)注的不僅是語句本身的語法正確性,而且關(guān)注所訪問的數(shù)據(jù)庫是否支持,例如有的數(shù)據(jù)庫不支持存儲過程操作,則發(fā)送調(diào)用存儲過程的語句即拋出異常。有三個(gè)類用于向數(shù)據(jù)庫發(fā)送SQL語句:

(1)Statement類,調(diào)用其createStatement()方法可以創(chuàng)建語句對象,然后利用該語句對象可以向數(shù)據(jù)庫發(fā)送具體的SQL語句。例如:

Stringquery=“select*fromtable1”;//查詢語句

Satement

st=con.createStatement();//或用帶參數(shù)的createStatement()方法

ResultSet

rs=st.executeQuery(query);//發(fā)送SQL語句,獲得結(jié)果

(2)PreparedStatement類,調(diào)用其方法prepareStatement()創(chuàng)建一編譯預(yù)處理語句對象,可以向數(shù)據(jù)庫發(fā)送帶有參數(shù)的SQL語句。該類有一組setXXX方法,用設(shè)置參數(shù)值。這些參數(shù)被傳送到數(shù)據(jù)庫,預(yù)處理語句被執(zhí)行。這個(gè)過程類似于給函數(shù)傳遞參數(shù)之后執(zhí)行函數(shù),完成預(yù)期的處理。使用PreparedStatement與使用Statement相比較有較高的效率,關(guān)于這一點(diǎn)詳見后面相關(guān)部分的闡述。PreparedStatement

ps;

ResultSet

rs=null;Stringquery="selectname,age,addrfromxsdawhereaddr=?";

ps=con.prepareStatement(query);ps.setString(1,"hei");

rs=ps.executeQuery();

(3)CallableStatement類的方法prepareCall()可用于創(chuàng)建對象,該對象用于向數(shù)據(jù)庫發(fā)送一調(diào)用某存儲過程的SQL語句。prepareCall()和prepareStatement()一樣,所創(chuàng)建的語句允許帶有參數(shù),用setXXX()設(shè)置輸入?yún)?shù),即IN參數(shù),同時(shí)需接收和處理OUT參數(shù)、INOUT參數(shù)以及存儲過程的返回值,概要說明其使用方法的語句例子如下:CallableStatement

cstmt;

ResultSet

rs;

cstmt=con.prepareCall("{?=callstat(?,?)}");//stat是一存儲過程的名字,它有兩個(gè)參數(shù),且有返回值

cstmt.setString(2,”JavaProgrammingLanguage”);

rs=cstmt.executeQuery();5.檢索結(jié)果數(shù)據(jù)庫執(zhí)行傳送到的SQL語句,結(jié)果有多種存儲位置,這與所執(zhí)行的語句有關(guān)。以查詢語句select為例,其結(jié)果需返回到程序中一結(jié)果集對象,即前面語句例子中的ResultSet之對象rs。rs可看作是一個(gè)表子集,有若干行和若干列,行列的具體數(shù)量與查詢條件及滿足查詢條件的記錄數(shù)有關(guān)。要瀏覽該表內(nèi)容可以借助ResultSet類的相關(guān)方法完成。例如行指針移動方法rs.next()和取列內(nèi)容的方法rs.getXXX()等。若是執(zhí)行數(shù)據(jù)更新語句update,則返回的是成功進(jìn)行更新的數(shù)據(jù)庫記錄行數(shù),所以,檢索結(jié)果操作要依程序的具體內(nèi)容而定。

6.關(guān)閉連接完成對數(shù)據(jù)庫得操作之后應(yīng)關(guān)閉與常用數(shù)據(jù)庫的連接。關(guān)閉連接使用close()方法。格式如下:

con.close();2.1.4JDBC常用APIJDBCAPI提供的類和接口是在java.sql包中定義的。1.DriverManager類DriverManager類的常用方法:1)staticvoidderegisterDriver(Driverdriver)方法,從DriverManager的列表中刪除一個(gè)驅(qū)動程序。2)static

Connection

getConnection(String

url)方法,建立到給定數(shù)據(jù)庫URL的連接。3)static

Connection

getConnection(String

url,Properties

info)方法,用給定的數(shù)據(jù)庫URL和相關(guān)信息(用戶名、用戶密碼等屬性)來創(chuàng)建一個(gè)連接。4)static

Connection

getConnection(String

url,String

user,String

password)方法,按給定的數(shù)據(jù)庫URL、用戶名和用戶密碼創(chuàng)建一個(gè)連接。5)static

Driver

getDriver(String

url)方法,查找給定URL下的驅(qū)動程序。6)static

Enumeration<Driver> getDrivers()方法,獲得當(dāng)前調(diào)用方可以訪問的所有已加載JDBC驅(qū)動程序的Enumeration。7)static

int

getLoginTimeout()方法,獲得驅(qū)動程序連接到某一數(shù)據(jù)庫時(shí)可以等待的最長時(shí)間,以秒為單位。8)static

PrintWriter

getLogWriter()方法,檢索記錄寫入器。9)static

voidprintln(String

message)方法,將一條消息打印到當(dāng)前JDBC記錄流中。10)static

voidregisterDriver(Driver

driver)方法,向DriverManager注冊給定驅(qū)動程序。2.Connection類Connection類有如下常量:1)static

int

TRANSACTION_NONE指示不支持事務(wù)。2)static

int

TRANSACTION_READ_UNCOMMITTED說明一個(gè)事務(wù)在提交前其變化對于其他事務(wù)而言是可見的。這樣可能發(fā)生臟讀(dirtyread)、不可重復(fù)讀(unrepeatedread)和虛讀(phantomread)。3)static

int

TRANSACTION_READ_COMMITTED說明讀取未提交的數(shù)據(jù)是不允許的。防止發(fā)生臟讀的情況,但不可重復(fù)讀和虛讀仍有可能發(fā)生。4)static

int

TRANSACTION_REPEATABLE_READ說明事務(wù)保證能夠再次讀取相同的數(shù)據(jù)而不會失敗,但虛讀有可能發(fā)生。5)static

int

TRANSACTION_SERIALIZABLE指示防止發(fā)生臟讀、不可重復(fù)讀和虛讀的常量。Connection類的常用方法:1)voidclearWarnings()方法,清除此Connction對象報(bào)告的所有警告。2)voidclose()方法,斷開此Connction對象和數(shù)據(jù)庫的連接,而不是等待它們被自動釋放。3)voidcommit()方法,使自從上一次提交/回滾以來進(jìn)行的所有更改成為持久更改,并釋放此Connction

對象當(dāng)前保存的所有數(shù)據(jù)庫鎖定。4)Statement

createStatement()方法,創(chuàng)建一個(gè)Statement對象,用來將SQL語句發(fā)送到數(shù)據(jù)庫。5)Statement

createStatement(int

resultSetType,int

resultSetConcurrency)方法,創(chuàng)建一個(gè)Statement對象,該對象將生成具有給定類型和并發(fā)性的ResultSet對象。6)Statement

createStatement(int

resultSetType,int

resultSetConcurrency,int

resultSetHoldability)方法,創(chuàng)建一個(gè)Statement對象,該對象將生成具有給定類型、并發(fā)性和可保存性的ResultSet對象。

3.Statement類

Statement類的常用方法包括:1)voidaddBatch(String

sql)方法,將給定的SQL命令添加到此Statement對象的當(dāng)前命令列表中。2)voidclearBatch()方法,清空此Statement對象的當(dāng)前SQL命令列表。3)voidclose()方法,立即釋放此Statement對象的數(shù)據(jù)庫和JDBC資源,而不是等待該對象自動關(guān)閉時(shí)發(fā)生此操作。4)boolean

execute(String

sql)方法,執(zhí)行給定的SQL語句,該語句可能返回多個(gè)結(jié)果。5)int[]executeBatch()方法,將一批命令提交給數(shù)據(jù)庫來執(zhí)行,如果全部命令執(zhí)行成功,則返回更新計(jì)數(shù)組成的數(shù)組。6)ResultSet

executeQuery(String

sql)方法,執(zhí)行給定的SQL語句,該語句返回單個(gè)ResultSet對象。4.PreparedStatement類1)voidaddBatch()方法,將一組參數(shù)添加到此PreparedStatement對象的批處理命令中。2)boolean

execute()方法,在此PreparedStatement對象中執(zhí)行SQL語句,該語句可以是任何種類的SQL語句。3)ResultSet

executeQuery()方法,在此PreparedStatement對象中執(zhí)行SQL查詢,并返回該查詢生成的ResultSet對象。

4)int

executeUpdate()方法,在此PreparedStatement對象中執(zhí)行SQL語句,該語句必須是一個(gè)SQLINSERT、UPDATE或DELETE語句;或者是一個(gè)什么都不返回的SQL語句,比如DDL語句。5)ResultSetMetaData

getMetaData()方法,檢索包含有關(guān)ResultSet

對象的列消息的ResultSetMetaData

對象,ResultSet

對象將在執(zhí)行此PreparedStatement對象時(shí)返回。6)ParameterMetaData

getParameterMetaData()方法,檢索此PreparedStatement對象的參數(shù)的編號、類型和屬性。5.CallableStatement類

CallableStatement類的方法主要有三種,設(shè)置參數(shù)的系列set方法和獲取參數(shù)的系列g(shù)et方法以及注冊輸出參數(shù)方法。下面分別示例說明之。1)boolean

getBoolean(int

parameterIndex)方法,以Java編程語言中boolean值的形式檢索指定的JDBCBIT參數(shù)的值。2)boolean

getBoolean(String

parameterName)方法,以Java編程語言中boolean值的形式檢索JDBCBIT參數(shù)的值。3)bytegetByte(int

parameterIndex)方法,以Java編程語言中byte的形式檢索指定的JDBCTINYINT參數(shù)的值。4)shortgetShort(int

parameterIndex)方法,以Java編程語言中short值的形式檢索指定的JDBCSMALLINT參數(shù)的值。5)String

getString(int

parameterIndex)方法,以Java編程語言中String的形式檢索指定的JDBCCHAR、VARCHAR或LONGVARCHAR參數(shù)的值。6)voidregisterOutParameter(int

parameterIndex,int

sqlType)方法,以parameterIndex為參數(shù)順序位置將OUT參數(shù)注冊為JDBC類型sqlType。必須在執(zhí)行存儲過程之前調(diào)用此方法。由sqlType指定的OUT參數(shù)的JDBC類型確定必須用于get方法來讀取該參數(shù)值的Java類型。這種registerOutParameter應(yīng)該在參數(shù)是JDBC類型NUMERIC或DECIMAL時(shí)使用。6.ResultSet類該類的幾個(gè)常量的作用如下:1)static

int

CLOSE_CURSORS_AT_COMMIT,該常量指示調(diào)用Cmit

方法時(shí)應(yīng)該關(guān)閉ResultSet對象。2)static

int

CONCUR_READ_ONLY,該常量指示不可以更新的ResultSet對象的并發(fā)模式。3)static

int

CONCUR_UPDATABLE,該常量指示可以更新的ResultSet對象的并發(fā)模式。4)static

int

FETCH_FORWARD,該常量指示將按正向(即從第一個(gè)到最后一個(gè))處理結(jié)果集中的行。5)static

int

FETCH_REVERSE,該常量指示將按反向(即從最后一個(gè)到第一個(gè))處理結(jié)果集中的行處理。6)static

int

FETCH_UNKNOWN,該常量指示結(jié)果集中的行的處理順序未知。7)static

int

HOLD_CURSORS_OVER_COMMIT,該常量指示調(diào)用Cmit

方法時(shí)不應(yīng)關(guān)閉對象。8)static

int

TYPE_FORWARD_ONLY,該常量指示指針只能向前移動的ResultSet對象的類型。10)static

int

TYPE_SCROLL_INSENSITIVE,該常量指示可滾動但通常不受其他的更改影響的ResultSet對象的類型。11)static

int

TYPE_SCROLL_SENSITIVE,該常量指示可滾動并且通常受其他的更改影響的ResultSet對象的類型。ResultSet類的方法按其功能可以分為二類,即指針移動方法和數(shù)據(jù)操作方法。這里僅舉例說明這兩類方法的功能。1)boolean

absolute(int

row)方法,將指針移動到此ResultSet對象的給定行編號。2)voidafterLast()方法,將指針移動到此ResultSet對象的末尾,正好位于最后一行之后。3)voidbeforeFirst()方法,將指針移動到此ResultSet對象的開頭,正好位于第一行之前。4)boolean

first()方法,將指針移動到此ResultSet對象的第一行。5)boolean

isAfterLast()方法,檢索指針是否位于此ResultSet對象的最后一行之后。6)boolean

isBeforeFirst()方法,檢索指針是否位于此ResultSet對象的第一行之前。7)boolean

isFirst()方法,檢索指針是否位于此ResultSet對象的第一行。8)boolean

isLast()方法,檢索指針是否位于此ResultSet對象的最后一行。9)boolean

last()方法,將指針移動到此ResultSet對象的最后一行。10)voidmoveToCurrentRow()方法,將指針移動到記住的指針位置,通常為當(dāng)前行。11)voidmoveToInsertRow()方法,將指針移動到插入行。將指針置于插入行上時(shí),當(dāng)前的指針位置會被記住。插入行是一個(gè)與可更新結(jié)果集相關(guān)聯(lián)的特殊行。它實(shí)際上是一個(gè)緩沖區(qū),在將行插入到結(jié)果集前可以通過調(diào)用更新方法在其中構(gòu)造新行。當(dāng)指針位于插入行上時(shí),僅能調(diào)用更新方法、獲取方法以及insertRow方法。每次在調(diào)用insertRow之前調(diào)用此方法時(shí),必須為結(jié)果集中的所有列分配值。在對列值調(diào)用獲取方法之前,必須調(diào)用更新方法。12)boolean

next()方法,將指針從當(dāng)前位置下移一行。ResultSet指針最初位于第一行之前;第一次調(diào)用next方法使第一行成為當(dāng)前行;第二次調(diào)用使第二行成為當(dāng)前行,依此類推。如果開啟了對當(dāng)前行的輸入流,則調(diào)用next方法將隱式關(guān)閉它。讀取新行時(shí),將清除ResultSet對象的警告鏈。7.Date類

java.sql.Date與java.util.Date配合使用可以方便地處理應(yīng)用程序中的日期型數(shù)據(jù)。下面的代碼段可以對此做簡要說明:

Dated1=newDate();//d1為當(dāng)前日期,某學(xué)生今日在圖書館借閱圖書

int

maxDays=60;//一本書的規(guī)定借閱天數(shù)60天

Dated2=newDate(d1.getTime()+60*24*60*60*1000);//d2為應(yīng)還書日期若要與數(shù)據(jù)庫交互,例如將該日期寫入數(shù)據(jù)庫相應(yīng)字段,需借助java.sql.Date:

rs.moveToInsertRow();……java.sql.Dated3=newjava.sql.Date(d2.getTime);

rs.updateDate(“應(yīng)還日期”,d3);//將所借之書的應(yīng)還日期寫入數(shù)據(jù)庫

……

rs.insertRow();8.元數(shù)據(jù)類Java定義的元數(shù)據(jù)(MetaData)有以下三種:DatabaseMetadata用于獲得關(guān)于數(shù)據(jù)庫和數(shù)據(jù)表的信息。ResultSetMetaData用于獲得關(guān)于結(jié)果集的信息。ParameterMetaData用于獲得預(yù)處理語句預(yù)處理語句對象參數(shù)的類型和屬性信息。2.1.5數(shù)據(jù)庫連接范例1.連接Oracle數(shù)據(jù)庫(用thin模式)

Class.forName(“oracle.jdbc.driver.OracleDriver”);Stringurl=“jdbc:oracle:thin:@localhost:1521:db”;Connectioncon=DriverManager.getConnection(url,user,password);Statementstmt=con.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CUNCUR_UPDATABLE);2.連接MySQL數(shù)據(jù)庫

Class.forName(“com.mysql.jdbc.Driver”);Stringurl=“jdbc:mysql://localhost:3306/db”;Connectioncon=DriverManager.getConnection(url,user,password);Statementstmt=con.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CUNCUR_UPDATABLE);3.連接SqlServer數(shù)據(jù)庫

Class.forName(“com.microsoft.jdbc.sqlserver.SQLServerDriver”);

Stringurl=“jdbc:microsoft:sqlserver://localhost:1433;DatabaseName=db”;Stringuser=”sa”;Stringpassword=””;

Connectioncon=DriverManager.getConnection(url,user,password);Statementstmt=con.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CUNCUR_UPDATABLE);2.2數(shù)據(jù)庫基本操作

2.2.1數(shù)據(jù)插入操作Insert語句格式如下:

INSERTINTO<表名>[(字段名[,字段名]…)]VALUES(常量[,常量]…)由于字段的類型不同,在values中的值的寫法要求也不同。概括起來說有如下幾點(diǎn):(1)數(shù)值型字段,可以直接寫數(shù)值;(2)字符型字段,其值要加單引號。(3)日期型字段,其值要加單引號,同時(shí)還要注意年、月、日的次序。例如,要向表member中插入一行數(shù)據(jù)的SQL語句是:INSERTINTOmember(name,age,sex,wage,addr)VALUES('LiMing',40,'男',4500,'北京市')INSERTINTOemp(empno,hiredate)VALUES(8888,to_date(‘2002-09-08’,’YYYY-MM-DD’))向表中插入NULL值需要滿足以下幾點(diǎn):(1)插入NULL的列在表中的定義不能為NOTNULL。(2)插入NULL的列在表的定義不能為主鍵或作為另外表的外鍵。(3)插入NULL的列在表的定義里不能有唯一的約束。對很多數(shù)據(jù)庫而言,對數(shù)據(jù)的插入、刪除和更新操作都有兩種可選的操作模式:直接使用SQL語句插入(或更新、刪除)模式和通過可更新的結(jié)果集對象間接插入(或更新、刪除)。且記,我們在創(chuàng)建語句對象時(shí)用下面的形式:

Statementstmt=con.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CUNCUR_UPDATABLE);其中,參數(shù)ResultSet.CUNCUR_UPDATABLE的作用正是為了使該語句生成的結(jié)果對象是可更新結(jié)果集,它可被用來插入、更新、刪除記錄內(nèi)容。下面的程序段說明了如何利用可更新結(jié)果集進(jìn)行數(shù)據(jù)插入:

rs.moveToInsertRow();

rs.updateString("name","'LiMing");rs.updateInt("age",40);

rs.updateString("sex","男");rs.updateInt("wage",50000);

rs.updateString("addr","北京市");

rs.insertRow();試比較若為交互操作引入變量在上面的操作中和在SQLINSERT語句中的情形,何者更方便是一目了然的。看看下面的SQLINSERT語句,體會一下惱人的拼串過程:

Stringsqlins="INSERTINTOstudentsvalues('"+sno+"','"+name+"','"+sex+"','"+birthday+"','"+"','"+department+"')";2.2.2數(shù)據(jù)刪除操作Delete語句的格式為:

DELETEFROM<表名>WHERE<條件表達(dá)式>例如:

DELETEFROMtable1WHERENo=7658從表table1中刪除一條記錄,其字段No的值為7658。使用可更新結(jié)果集的刪除操作,參見下面的代碼段:stmt=con.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_UPDADABLE);con.setAutoCommit(false);Stringsqlst=“select*frommember”;

rs=stmt.executeQuery(sqlst);rs.relative(4);//移動到第4條記錄

rs.deleteRow();//從結(jié)果集和底層數(shù)據(jù)庫刪除該記錄

mit();2.2.3數(shù)據(jù)更新操作數(shù)據(jù)更新語句的命令格式為:

UPDATE<table_name>SETcolume_name=‘xxx’WHERE<條件表達(dá)式>例如語句:

UPDATEEMPSETJOB=’MANAGER’WHERENAME=’MATIN’對數(shù)據(jù)表EMP中姓名為MATIN的職工數(shù)據(jù)進(jìn)行了修改,將其工作名稱改為MANAGER。向數(shù)據(jù)庫發(fā)送數(shù)據(jù)更新的SQL語句是通過調(diào)用方法executeUpdate()完成的:Stringss="updatexsdasetage=age+1wherename='yang'";

stmt.executeUpdate(ss);下面的代碼說明使用可更新結(jié)果集進(jìn)行更新操作的方法。

rs=stmt.executeQuery("select*frommemberwhereage=16");

rs.first();rs.updateInt("wage",3000);

rs.updateRow();

rs.next();rs.updateInt("wage",4000);

rs.updateRow();

rs.next();

rs.updateString("addr","上海市");

rs.updateRow();上面的代碼對連續(xù)3條記錄的wage字段和addr字段值進(jìn)行了更新操作。2.2.4數(shù)據(jù)查詢操作查詢語句的語句格式如下:

SELECT[DISTINCT]{column1,column2,…}FROMtablename

WHERE{conditions}GROUPBY{conditions}HAVING{conditions}

ORDERBY{conditions}[ASC/DESC];說明:SELECT子句用于指定檢索數(shù)據(jù)庫中的哪些列,若要檢索所有列可以不必列出所有列名,只用*表示即可。FROM子句用于指定從哪一個(gè)表或者視圖中檢索數(shù)據(jù)。選項(xiàng)DISTINCT指明顯式結(jié)果不重復(fù),無此選項(xiàng)則顯示所有記錄可能重復(fù)。例如下面的語句只顯示姓名不同的記錄:

selectdistinctNamefromperson;WHERE子句用于指定查詢條件,若condition條件表達(dá)式的值為TRUE,則檢索相應(yīng)的行,若條件表達(dá)式的值為FALSE,則不會檢索該行數(shù)據(jù)。GROUPBY指出記錄分組的條件,例如進(jìn)行分組統(tǒng)計(jì)。HAVING則是用于限制分組統(tǒng)計(jì)的結(jié)果。例如統(tǒng)計(jì)emp表中不同部門(depno)不同崗位(job)的平均工資(AVG(sal))大于3000的所有記錄的語句如下:

SELECTdepno,job,AVG(sal)FROMempGROUPBYdepno,jobHAVINGAVG(sal)>3000;注意:HAVING子句必須跟在GROUPBY子句的后面。ORDERBY子句指出查詢結(jié)果排序顯示,可為升序(ASC)或可為降序(DESC)排列。2.2.5事務(wù)處理所謂事務(wù),概指一系列的數(shù)據(jù)庫操作,這些操作要么全做,要么全不做,是一個(gè)不可分割的工作單元,也可以說是數(shù)據(jù)庫應(yīng)用程序中的一個(gè)基本邏輯單元。它可能是一條SQL語句、一組SQL語句或者一個(gè)完整的程序。這體現(xiàn)的是事務(wù)的原子性需求,對事務(wù)還有其他的需求如一致性、隔離性、持久性。JDBC事務(wù)處理可采用隔離級別控制數(shù)據(jù)讀取操作。JDBC支持5個(gè)隔離級別設(shè)置,其名字和含義如下所示:staticintTRANSACTION_NONE不支持事務(wù)staticintTRANSACTION_READ_COMMITED臟讀、不可重復(fù)讀、錯(cuò)誤讀取可能出現(xiàn)staticintTRANSACTION_READ_UNCOMMITED禁止臟讀,不可重復(fù)讀、錯(cuò)誤讀取可能出現(xiàn)staticintTRANSACTION_REPEATABLE_READ禁止臟讀、不可重復(fù)讀,錯(cuò)誤讀取可能出現(xiàn)staticintTRANSACTION_SERIALIZABLE禁止臟讀、不可重復(fù)讀、錯(cuò)誤讀取。上面的5個(gè)常量是Connection中提供的。同樣Connection提供了方法進(jìn)行隔離級別設(shè)置:

setTransactionIsolation(Connection.TRANSACTION_REPEATABLE_READ)一個(gè)事務(wù)也許包含幾個(gè)任務(wù),正象超市里面完成一個(gè)事務(wù)也要包括幾個(gè)任務(wù)一樣。超市里的一個(gè)事務(wù)對應(yīng)于一次消費(fèi)活動的全過程。它是由若干個(gè)任務(wù)構(gòu)成的。確定購買項(xiàng)目,登記每個(gè)項(xiàng)目,然后計(jì)算總額,之后支付。只有當(dāng)每個(gè)任務(wù)結(jié)束后,事務(wù)才結(jié)束。如果其中的一個(gè)任務(wù)失敗,則事務(wù)失敗,前面完成的任務(wù)也要恢復(fù)。這是基本性質(zhì)。Connection中下面三個(gè)方法完成基本的事務(wù)管理:1)setAutoCommit(booleantrue/false)方法,設(shè)置自動提交屬性AutoCommit,默認(rèn)為true。2)rollback()方法,回滾事務(wù)。3)commit()方法,事務(wù)提交。在調(diào)用了commit()方法之后,所有為這個(gè)事務(wù)創(chuàng)建的結(jié)果集對象都被關(guān)閉了,除非通過createStatement()方法傳遞了參數(shù):HOLD_CURSORS_OVER_COMMIT其功能相對的另一個(gè)參數(shù)為:CLOSE_CURSORS_AT_COMMIT在commit()方法被調(diào)用時(shí)關(guān)閉ResultSet對象。事務(wù)中若包含多個(gè)任務(wù),當(dāng)事務(wù)失敗時(shí),也許其中部分任務(wù)不需要被回滾,例如處理一個(gè)訂單要完成3個(gè)任務(wù):更新消費(fèi)者帳戶表,定單插入到待處理的定單表,給消費(fèi)者發(fā)一確認(rèn)電子郵件。如果上述3個(gè)任務(wù)中完成了前2個(gè)只是最后一個(gè)因?yàn)猷]件服務(wù)器掉線而未完成,那么不需要對整個(gè)事務(wù)回滾。如何處理有數(shù)量選擇與控制的回滾操作?我們需要引進(jìn)保存點(diǎn)(savepoint)來控制回滾的數(shù)量。Jdbc3.0支持保存點(diǎn)的操作。所謂保存點(diǎn),就是對事務(wù)的某些子任務(wù)設(shè)置符號標(biāo)識,用以為回滾操作提供位置指示。關(guān)于保存點(diǎn)的方法主要有以下三個(gè):(1)setSavepoint(“保存點(diǎn)名稱”)方法,在某子任務(wù)前設(shè)置一保存點(diǎn)。(2)releaseSavepoint(“保存點(diǎn)名稱”)方法,釋放一指定名稱的保存點(diǎn)。(3)rollback(“保存點(diǎn)名稱”)方法,指示事務(wù)回滾到指定的保存點(diǎn)。2.3數(shù)據(jù)庫存取優(yōu)化

2.3.1常用技術(shù)(1)優(yōu)化SQL語句的執(zhí)行效率(2)定義和調(diào)用存儲過程(3)采用編譯預(yù)處理(4)采用數(shù)據(jù)庫連接池技術(shù)(5)選擇合適的JDBC驅(qū)動程序(6)優(yōu)化建立的連接2.3.2編譯預(yù)處理首先了解一下PreparedStatement這個(gè)類。PreparedStatement是Statement的一個(gè)子類。PreparedStatement類與Statement類的一個(gè)重要區(qū)別是:用Statement定義的語句是一個(gè)功能明確而具體的語句,而用PreparedStatement類定義的SQL語句中則包含有一個(gè)或多個(gè)問號(“?”)占位符,它們對應(yīng)于多個(gè)IN參數(shù)。帶著占位符的SQL語句被編譯,而在后續(xù)執(zhí)行過程中,這些占位符需要用setXXX方法設(shè)置為具體的IN參數(shù)值,這些語句發(fā)送至數(shù)據(jù)庫獲得執(zhí)行。下面給出若干編譯預(yù)處理語句例子說明PreparedStatement的用法:首先創(chuàng)建對象:PreparedStatement

pstmt=con.prepareStatement(“updatetable1setx=?wherey=?”);在對象pstmt中包含了語句“updatetable1setx=?wherey=?”,該語句被發(fā)送到DBMS進(jìn)行編譯預(yù)處理,為執(zhí)行做準(zhǔn)備。然后為每個(gè)IN參數(shù)設(shè)定參數(shù)值,即每個(gè)占位符?(Placeholder)對應(yīng)一個(gè)參數(shù)值。設(shè)定參數(shù)值是通過調(diào)用setXXX方法實(shí)現(xiàn)的,其中XXX是與參數(shù)相對應(yīng)的類型,加入上面例子中參數(shù)類型為long,則用下面的代碼為參數(shù)設(shè)定值:pstmt.setLong(1,123456789);pstmt.setLong(2,987654321);這里的1和2是與占位符從左到右的次序相對應(yīng)的序號。注意它們不是從0開始計(jì)數(shù)的。最后執(zhí)行語句

Pstmt.executeUpdate();程序例2.1用于說明編譯預(yù)處理語句的使用方法。2.3.3調(diào)用存儲過程很多數(shù)據(jù)庫支持存儲過程功能。可以在數(shù)據(jù)庫中定義存儲過程,在Java中則可以調(diào)用存儲過程完成某些處理。這也是提高數(shù)據(jù)存取效率的方法。和編譯預(yù)處理操作提高效率的機(jī)制類似,采用存儲過程也是基于避免頻繁地與數(shù)據(jù)庫交互和更多地重用代碼以期減少時(shí)間開銷從而提高效率的。關(guān)于存儲過程的定義的語法,可參閱介紹數(shù)據(jù)庫的書籍資料加以掌握。這里僅對Java中調(diào)用存儲過程的語法和應(yīng)用進(jìn)行討論。假設(shè)現(xiàn)已在SQLServer中建立如下兩個(gè)存儲過程,一個(gè)是無參的,一個(gè)是帶參數(shù)的。無參數(shù)存儲過程getCourseName用于按課程號查詢課程名。createproceduregetCourseNameasselectdistinctcourseNamefromgrade,coursewheregrade.courseID=course.courseID有參數(shù)存儲過程stat用于統(tǒng)計(jì)指定課程的平均分?jǐn)?shù)和學(xué)生數(shù),學(xué)生數(shù)用函數(shù)返回值返回給調(diào)用者,平均分?jǐn)?shù)則是通過輸出參數(shù)傳遞給調(diào)用者。@avgGradefloatoutput說明參數(shù)@avgGrade類型為float,output指其為輸出參數(shù),即從存儲過程返回時(shí)向調(diào)用程序(Java程序)傳值,其作用

溫馨提示

  • 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)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論