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