1.Class.ForName("xxx");加載驅(qū)動(dòng)器類
2.連接到數(shù)據(jù)庫(kù)
Connection con = DriverManager.getConnection(url, user, passWord);3.創(chuàng)建statement對(duì)象PReparedStatement statement = con.prepareStatement(sql); Statement sta = con.createStatement();4.執(zhí)行sqlResultSet set = statement.executeQuery();sta.execute(sql);sta.getResultSet();executeUpdate方法既可以執(zhí)行諸如INSERT、 UPDATE和DELETE之類的操作,也可以執(zhí)行諸如CREATE TABLE和DROP TABLE之類的數(shù)據(jù)定義語句。但是,執(zhí)行SELECT查詢時(shí)必須使用executeQuery方法。另外還有一個(gè)execute方法可以執(zhí)行任意的SQL語句,此方法通常只用于用戶提供的交互式查詢。
5.解析ResultSet得到數(shù)據(jù)
while(sta.next()){sta.getString(1);sta.getString("name");} ResultSet類的迭代方法與java.util.Iterator接口稍有不同。對(duì)于ResultSet類,迭代器初始化時(shí)被設(shè)定在第一行之前的位置,必須調(diào)用next方法將它移動(dòng)到第一行。另外,它沒有hasNext方法,我們需要不斷地調(diào)用next,直至該方法返回false。不同的數(shù)據(jù)類型有不同的訪問器,比如getString和getdouble。每個(gè)訪問器都有兩種形式,一種接受數(shù)字參數(shù),另一種接受字符串參數(shù)。當(dāng)使用數(shù)字參數(shù)時(shí),我們指的是該數(shù)字所對(duì)應(yīng)的列。例如, rs.getString(1)返回的是當(dāng)前行中第一列的值。與數(shù)組的索引不同,數(shù)據(jù)庫(kù)的列序號(hào)是從1開始計(jì)算的。 當(dāng)使用字符串參數(shù)時(shí),指的是結(jié)果集中以該字符串為列名的列。例如, rs.getDouble("Price")返回列名為Price的列所對(duì)應(yīng)的值。使用數(shù)字參數(shù)效率更高一些,但是使用字符串參數(shù)可以使代碼易于閱讀和維護(hù)。當(dāng)get方法的類型和列的數(shù)據(jù)類型不一致時(shí),每個(gè)get方法都會(huì)進(jìn)行合理的類型轉(zhuǎn)換。例如,調(diào)用rs.getString("Price")時(shí),該方法會(huì)將Price列的浮點(diǎn)值轉(zhuǎn)換成字符串。StatementResultSet executeQuery(String sqlQuery)執(zhí)行給定字符串中的SQL語句,并返回一個(gè)用于查看查詢結(jié)果的ResultSet對(duì)象。int executeUpdate(String sqlStatement)執(zhí)行字符串中指定的INSERT、 UPDATE或DELETE等SQL語句。還可以執(zhí)行數(shù)據(jù)定義語言( Data Definition Language, DDL)的語句,如CREATE TABLE。返回受影響的記錄總數(shù),如果是沒有更新計(jì)數(shù)的語句,則返回-1。boolean execute(String sqlStatement)執(zhí)行字符串中指定的SQL語句。可能會(huì)產(chǎn)生多個(gè)結(jié)果集和更新數(shù)。如果第一個(gè)執(zhí)行結(jié)果是結(jié)果集,則返回true;反之,返回false。調(diào)用getResultSet或getUpdateCount方法可以得到第一個(gè)執(zhí)行結(jié)果。請(qǐng)參見第4.5.4節(jié)中關(guān)于處理多結(jié)果集的詳細(xì)信息。ResultSet getResultSet()返回前一條查詢語句的結(jié)果集。如果前一條語句未產(chǎn)生結(jié)果集,則返回null值。對(duì)于每一條執(zhí)行過的語句,該方法只能被調(diào)用一次。int getUpdateCount()返回受前一條更新語句影響的行數(shù)。如果前一條語句未更新數(shù)據(jù)庫(kù),則返回-1。對(duì)于每一條執(zhí)行過的語句,該方法只能被調(diào)用一次。void close()關(guān)閉Statement對(duì)象以及它所對(duì)應(yīng)的結(jié)果集。boolean isClosed() 如果語句被關(guān)閉,則返回true。ResultSetboolean next()將結(jié)果集中的當(dāng)前行向前移動(dòng)一行。如果已經(jīng)到達(dá)最后一行的后面,則返回false。注意,初始情況下必須調(diào)用該方法才能轉(zhuǎn)到第一行。Xxx getXxx(int columnNumber)Xxx getXxx(String columnName)( Xxx指數(shù)據(jù)類型,例如int、 double、 String、 Date等。)用給定的列序號(hào)或列標(biāo)簽返回該列的值,并將值轉(zhuǎn)換成指定類型。列標(biāo)簽是SQL的AS字句中指定的標(biāo)簽,在沒有使用AS時(shí),它就是列名。int findColumn(String columnName)根據(jù)給定的列名,返回該列的序號(hào)。void close()立即關(guān)閉當(dāng)前的結(jié)果集。boolean isClosed() 如果語句被關(guān)閉,則返回true。 每個(gè)Connection對(duì)象都可以創(chuàng)建一個(gè)或一個(gè)以上的Statement對(duì)象。同一個(gè)Statement對(duì)象可以用于多個(gè)不相關(guān)的命令和查詢。但是,一個(gè)Statement對(duì)象最多只能打開一個(gè)結(jié)果集。如果需要執(zhí)行多個(gè)查詢操作,且需要同時(shí)分析查詢結(jié)果,那么必須創(chuàng)建多個(gè)Statement對(duì)象。這看上去似乎很有局限性。但實(shí)際上,我們通常并不需要同時(shí)處理多個(gè)結(jié)果集。如果結(jié)果集相互關(guān)聯(lián),我們就可以使用組合查詢,這樣就只需要分析一個(gè)結(jié)果。對(duì)數(shù)據(jù)庫(kù)進(jìn)行組合查詢比使用Java程序遍歷多個(gè)結(jié)果集要高效得多。當(dāng)使用完ResultSet、 Statement或Connection對(duì)象時(shí),應(yīng)立即調(diào)用close方法。這些對(duì)象都使用了規(guī)模較大的數(shù)據(jù)結(jié)構(gòu),所以我們不應(yīng)該等待垃圾回收器來處理它們。 如果Statement對(duì)象上有一個(gè)打開的結(jié)果集,那么調(diào)用close方法將自動(dòng)關(guān)閉該結(jié)果集。同樣地,調(diào)用Connection類的close方法將關(guān)閉該連接上的所有語句。預(yù)備語句preparedStatement
沒有必要在每次開始一個(gè)這樣的查詢時(shí)都建立新的查詢語句,而是準(zhǔn)備一個(gè)帶有宿主變量的查詢語句,每次查詢時(shí)只需為該變量填入不同的字符串就可以反復(fù)多次地使用該語句。這一技術(shù)改進(jìn)了查詢性能,每當(dāng)數(shù)據(jù)庫(kù)執(zhí)行一個(gè)查詢時(shí),它總是首先通過計(jì)算來確定查詢策略,以便高效地執(zhí)行查詢操作。通過事先準(zhǔn)備好查詢并多次重用它,我們就可以確保查詢所需的準(zhǔn)備步驟只被執(zhí)行一次。在預(yù)備查詢語句中,每個(gè)宿主變量都用“ ?”來表示。如果存在一個(gè)以上的變量,那么在設(shè)置變量值時(shí)必須注意“ ?”的位置。必須使用set方法將變量綁定到實(shí)際的值上。和ResultSet方法中的get方法類似,針對(duì)不同的數(shù)據(jù)類型也有不同的set方法。
statement.setInt(1, 7); 位置1表示第一個(gè)“ ?”。第二個(gè)參數(shù)指的是賦予宿主變量的值。如果想要重用已經(jīng)執(zhí)行過的預(yù)備查詢語句,那么除非使用set方法或調(diào)用clearParameters方法,否則所有宿主變量的綁定都不會(huì)改變。讀取COB數(shù)據(jù)
除了數(shù)字、字符串和日期之外,許多數(shù)據(jù)庫(kù)都可以存儲(chǔ)大對(duì)象,例如圖片或其他數(shù)據(jù)。在SQL中,二進(jìn)制大對(duì)象稱為BLOB,字符型大對(duì)象稱為CLOB。要讀取LOB,需要執(zhí)行SELECT語句,然后在ResultSet上調(diào)用getBlob和getClob方法,這樣就可以獲得Blob和Clob類型的對(duì)象。要從Blob中獲取二進(jìn)制數(shù)據(jù),可以調(diào)用getBytes或getInputStream。如果獲取了Clob對(duì)象,那么就可以通過調(diào)用getSubString或getCharacterStream來獲取其中的字符數(shù)據(jù)。要將LOB置于數(shù)據(jù)庫(kù)中,需要在Connection對(duì)象上調(diào)用createBlob或createClob,然后獲取一個(gè)用于該LOB的輸出流或?qū)懗銎鳎⒃搶?duì)象存儲(chǔ)到數(shù)據(jù)庫(kù)中。
Bloblong length()獲取該BLOB的長(zhǎng)度。byte[] getBytes(long startPosition, long length)獲取該BLOB中給定范圍的數(shù)據(jù)。InputStream getBinaryStream()InputStream getBinaryStream(long startPosition, long length)返回一個(gè)輸入流,用于讀取該BLOB中全部或給定范圍的數(shù)據(jù)。OutputStream setBinaryStream(long startPosition) 返回一個(gè)輸出流,用于從給定位置開始寫入該BLOB。Cloblong length()獲取該CLOB中的字符總數(shù)。String getSubString(long startPosition, long length)獲取該CLOB中給定范圍的字符。Reader getCharacterStream()Reader getCharacterStream(long startPosition, long length)返回一個(gè)讀入器(而不是流),用于讀取CLOB中全部或給定范圍的數(shù)據(jù)。Writer setCharacterStream(long startPosition) 返回一個(gè)寫出器(而不是流),用于從給定位置開始寫入該CLOB。多結(jié)果集在執(zhí)行存儲(chǔ)過程,或者在使用允許在單個(gè)查詢中提交多個(gè)SELECT語句的數(shù)據(jù)庫(kù)時(shí),一個(gè)查詢有可能會(huì)返回多個(gè)結(jié)果集。下面是獲取所有結(jié)果集的步驟:1. 使用execute方法來執(zhí)行SQL語句。2. 獲取第一個(gè)結(jié)果集或更新計(jì)數(shù)。3. 重復(fù)調(diào)用getMoreResults方法以移動(dòng)到下一個(gè)結(jié)果集(這個(gè)調(diào)用會(huì)自動(dòng)關(guān)閉前一個(gè)結(jié)果集)。4. 當(dāng)不存在更多的結(jié)果集或更新計(jì)數(shù)時(shí),完成操作。可滾動(dòng)和更新的結(jié)果集
默認(rèn)情況下,結(jié)果集是不可滾動(dòng)和不可更新的。為了從查詢中獲取可滾動(dòng)的結(jié)果集,必須使用以下方法得到一個(gè)不同的Statement對(duì)象
Statement sta = connect.createStatement(type,concurrenry)PreparedStatement s = connect.preparedStament(xxx,type,concurrenry)typeTYPE_FORWARD_ONLY 結(jié)果集不能滾動(dòng)TYPE_SCROLL_INSENSITIVE 結(jié)果集可以滾動(dòng),但對(duì)數(shù)據(jù)庫(kù)變化不敏感TYPE_SCROLL_SENSITIVE 結(jié)果集可以滾動(dòng),且對(duì)數(shù)據(jù)庫(kù)變化敏感concurrenryCONCUR_READ_ONLY 結(jié)果集不能用于更新數(shù)據(jù)庫(kù)(默認(rèn)值)CONCUR_UPDATABLE 結(jié)果集可以用于更新數(shù)據(jù)庫(kù) 生成了結(jié)果集之后就可以使用一些方法了set.next(),set.previous(),set.relative(n),set.absolute(n),first、 last、 beforeFirst和afterLast這些簡(jiǎn)便方法用于將光標(biāo)移動(dòng)到第一行、最后一行、第一行之前或最后一行之后。最后, isFirst、 isLast、 isBeforeFirst和isAfterLast用于測(cè)試光標(biāo)是否位于這些特殊位置上.并非所有的查詢都會(huì)返回可更新的結(jié)果集。如果查詢涉及多個(gè)表格的連接操作,那么它所產(chǎn)生的結(jié)果集將是不可更新的。如果查詢只涉及一個(gè)表格,或者在查詢時(shí)是使用主鍵連接多個(gè)表格的,那么它所產(chǎn)生的結(jié)果集將是可更新的結(jié)果集。可以調(diào)用ResultSet類中的getConcurrency方法來確定結(jié)果集是否是可更新的。 所有對(duì)應(yīng)于SQL類型的數(shù)據(jù)類型都配有updateXxx方法,比如updateDouble,updateString等。與getXxx方法相同,在使用updateXxx方法時(shí)必須指定列的名稱或序號(hào)。然后,你可以給該字段設(shè)置新的值。updateXxx方法改變的只是結(jié)果集中的行值,而非數(shù)據(jù)庫(kù)中的值。當(dāng)更新完行中的字段值后,必須調(diào)用updateRow方法,這個(gè)方法將當(dāng)前行中的所有更新信息發(fā)送給數(shù)據(jù)庫(kù)。調(diào)用updateRow方法就將光標(biāo)移動(dòng)到其他行上,那么所有的更新信息都將被行集丟棄,而且永遠(yuǎn)也不會(huì)被傳遞給數(shù)據(jù)庫(kù)。還可以調(diào)用cancelRowUpdates方法來取消對(duì)當(dāng)前行的更新。 如果想在數(shù)據(jù)庫(kù)中添加一條新的記錄,首先需要使用moveToInsertRow方法將光標(biāo)移動(dòng)到特定的位置,我們稱之為插入行( insert row)。然后,調(diào)用updateXxx方法在插入行的位置上創(chuàng)建一個(gè)新的行。在上述操作全部完成之后,還需要調(diào)用insertRow方法將新建的行發(fā)送給數(shù)據(jù)庫(kù)。完成插入操作后,再調(diào)用moveToCurrentRow方法將光標(biāo)移回到調(diào)用moveToInsertRow方法之前的位置。ResultSet類中的updateRow、 insertRow和deleteRow方法的執(zhí)行效果等同于SQL命令中的UPDATE、 INSERT和DELETE。不過,習(xí)慣于Java編程語言的程序員通常會(huì)覺得使用結(jié)果集來操控?cái)?shù)據(jù)庫(kù)要比使用SQL語句自然得多。行集
可滾動(dòng)的結(jié)果集雖然功能強(qiáng)大,卻有一個(gè)重要的缺陷:在與用戶的整個(gè)交互過程中,必須始終與數(shù)據(jù)庫(kù)保持連接。用戶也許會(huì)離開電腦旁很長(zhǎng)一段時(shí)間,而在此期間卻始終占有著數(shù)據(jù)庫(kù)連接。這種方式存在很大的問題,因?yàn)閿?shù)據(jù)庫(kù)連接屬于稀有資源。在這種情況下,我們可以使用行集。 RowSet接口繼承了ResultSet接口,卻無需始終保持與數(shù)據(jù)庫(kù)的連接。如下所示為javax.sql.rowset包提供的接口,它們都擴(kuò)展了RowSet接口:CachedRowSet允許在斷開連接的狀態(tài)下執(zhí)行相關(guān)操作。WebRowSet對(duì)象代表了一個(gè)被緩存的行集,該行集可以保存為xml文件。該文件可以移動(dòng)到Web應(yīng)用的其他層中,只要在該層中使用WebRowSet重新打開該文件即可。FilteredRowSet和JoinRowSet接口支持對(duì)行集的輕量級(jí)操作,它們等同于SQL中的SELECT和JOIN操作。上述兩個(gè)接口的操作對(duì)象是存儲(chǔ)在行集中的數(shù)據(jù),因此運(yùn)行時(shí)無需建立數(shù)據(jù)庫(kù)連接。JdbcRowSet是ResultSet接口的一個(gè)瘦包裝器。它從RowSet中繼承了get方法和set方法,從而將一個(gè)結(jié)果集轉(zhuǎn)換成一個(gè)bean。一個(gè)被緩存的行集包含了一個(gè)結(jié)果集中所有的數(shù)據(jù)。 CachedRowSet是ResultSet接口的子接口,所以你完全可以像使用結(jié)果集一樣來使用被緩存的行集。被緩存的行集有一個(gè)非常重要的優(yōu)點(diǎn):斷開數(shù)據(jù)庫(kù)連接后仍然可以使用行集。 甚至可以修改被緩存的行集中的數(shù)據(jù)。當(dāng)然,這些修改不會(huì)立即反饋到數(shù)據(jù)庫(kù)中。相反,必須發(fā)起一個(gè)顯式的請(qǐng)求,以便讓數(shù)據(jù)庫(kù)真正接受所有修改。此時(shí)CachedRowSet類會(huì)重新連接到數(shù)據(jù)庫(kù),并通過執(zhí)行SQL命令向數(shù)據(jù)庫(kù)中寫入所有修改后的數(shù)據(jù)。在填充了行集之后,數(shù)據(jù)庫(kù)中的數(shù)據(jù)發(fā)生了改變,這顯然容易造成數(shù)據(jù)不一致性。為了解決這個(gè)問題,參考實(shí)現(xiàn)會(huì)首先檢查行集中的原始值(即修改前的值)是否與數(shù)據(jù)庫(kù)中的當(dāng)前值一致。如果一致,那么修改后的值將覆蓋數(shù)據(jù)庫(kù)中的當(dāng)前值。否則,將拋出SyncProviderException異常,且不向數(shù)據(jù)庫(kù)寫回任何值。
RowSetString getURL()void setURL(String url)獲取或設(shè)置數(shù)據(jù)庫(kù)的URL。String getUsername()void setUsername(String username)獲取或設(shè)置連接數(shù)據(jù)庫(kù)所需的用戶名。String getPassword()void setPassword(String password)獲取或設(shè)置連接數(shù)據(jù)庫(kù)所需的密碼。String getCommand()void setCommand(String command)獲取或設(shè)置向行集中填充數(shù)據(jù)時(shí)需要執(zhí)行的命令。void execute()通過執(zhí)行使用setCommand方法設(shè)置的命令集來填充行集。為了使驅(qū)動(dòng)管理器可以獲得連接,必須事先設(shè)定URL、用戶名和密碼。CachedRowSetvoid execute(Connection conn)通過執(zhí)行使用setCommand方法設(shè)置的命令集來填充行集。該方法使用給定的連接,并負(fù)責(zé)關(guān)閉它。void populate(ResultSet result)將指定的結(jié)果集中的數(shù)據(jù)填充到被緩存的行集中。String getTableName()void setTableName(String tableName)獲取或設(shè)置數(shù)據(jù)庫(kù)表名稱,填充被緩存的行集時(shí)所需的數(shù)據(jù)來自于該表。int getPageSize()void setPageSize(int size)獲取和設(shè)置頁(yè)的尺寸。boolean nextPage()boolean previousPage()加載下一頁(yè)或上一頁(yè),如果要加載的頁(yè)存在,則返回ture。void acceptChanges()void acceptChanges(Connection conn)重新連接數(shù)據(jù)庫(kù),并寫回行集中修改過的數(shù)據(jù)。如果因?yàn)閿?shù)據(jù)庫(kù)中的數(shù)據(jù)已經(jīng)被修改而導(dǎo)致無法寫回行集中的數(shù)據(jù),該方法可能會(huì)拋出SyncProviderException異常。
新聞熱點(diǎn)
疑難解答
圖片精選
網(wǎng)友關(guān)注