我思故我強

          JDBC基礎知識


          JDBC基礎知識

          關鍵字: ? JDBC基礎知識????
          java 代碼
          1. 一、采用JDBC訪問數據庫的基本步驟: ??
          2. ????A.載入JDBC驅動程序 ??
          3. ????B.定義連接URL ??
          4. ????C.建立連接 ??
          5. ????D.創(chuàng)建Statement對象 ??
          6. ????E.執(zhí)行查詢或更新 ??
          7. ????F.結果處理 ??
          8. ????G.關閉連接 ??
          9. ??
          10. 二、載入JDBC驅動程序: ??
          11. 1 .為了使代碼盡可能地靈活,我們要避免對類名的引用進行硬編碼(hard-coding),因此我們可以采用從Properties文件中載入驅動程序的方法,也可以使用在服務器中配置數據源(DataSource)的方法來避免在代碼中硬編碼 ??
          12. ???? ??
          13. 2 .在開發(fā)過程中要保證CLASSPATH設定中包括驅動程序JAR文件所在的路徑。在WEB服務 ??
          14. 器上部署時要將JAR文件放在Web應用的WEB-INF/lib目錄下。如果多個Web應用使用相同的數據庫驅動程序可以將JAR文件放置在服務器使用的公共目錄<%CATALINA_HOME%>\common\lib中 ??
          15. ??
          16. 三、定義連接URL: ??
          17. ???????載入JDBC驅動程序之后,必須指定數據庫服務器位置。指向數據庫的URL所使用的協議是: ??
          18. ????jdbc:子協議,并且載入服務器的主機名、端口、數據庫名(或引用)。如:Oracle?的連接URL:  ??
          19. ????jdbc:oracle:thin: @192 .168. 0.71 : 1521 :UMV2 ??
          20. ????jdbc:oracle:采用Oracle驅動程序 ??
          21. ????thin:指連接服務器所采用的模式 ??
          22. ???? @192 .168. 0.71 :服務器的地址 ??
          23. ???? 1521 :服務器的監(jiān)聽端口 ??
          24. ????UMV2:數據庫名 ??
          25. ??
          26. 四、建立連接: ??
          27. ???? 1 .一個數據庫連接(Connection)可以通過其自身的getMetaData()來獲取它的自身信息 ??
          28. ???? 2 .默認情況下一個數據庫的連接是自動提交模式的(auto-commit),也就是說每當一個SQL語句 ??
          29. 被執(zhí)行后其改變結果都會被自動提交,如果auto-commit模式被關閉,那么方法commit()必須被顯式調用以提交改變結果,否則的話所有對數據庫操作的結果都不會被保存 ??
          30. ??
          31. 五、創(chuàng)建Statement對象: ??
          32. 在同一時間下,每個Statement對象只能打開一個ResultSet對象。所以,假如有兩個同樣結果的結果集在交叉訪問,那么這兩個結果集必定為兩個不同的Statement對象所創(chuàng)建。如果在打開一個新的結果集的時候存在一個已經打開的結果集,則這個已經存在的結果集會被隱式的關閉???? ??
          33. ??
          34. 六、執(zhí)行查詢或更新: ??
          35. ????在Statement對象中可以執(zhí)行如下的操作: ??
          36. ????A.查詢操作:executeQuery(SQL語句)??B.維護操作:executeUpdate(SQL語句) ??
          37. ????C.批處理操作:executeBath() ??
          38. ??
          39. 七、結果處理: ??
          40. ???? 1 .ResultSet中行的第一列索引為 1 ,而非 0 ,訪問ResultSet中的數據時要使用列名,而非索引 ??
          41. ???? 但要注意使用列名作為查詢條件是大小寫敏感的。 ??
          42. ??
          43. ???? 2 .JDBC1. 0 中,我們只能在ResultSet中向前移動;在JDBC2. 0 中,我們可以在ResultSet中向 ??
          44. ???? 下(next)或向上(previous)移動,同樣也可以移到特定的行(relative,absolute) ??
          45. ??
          46. 3 .默認情況下ResultSet是不可更新的,且只能向前移動。下面的代碼顯示了如何創(chuàng)建一個可滾動的、對更新敏感的ResultSet ??
          47. ??
          48. ???????Statement?stmt?=?con.createStatement( ??
          49. ??????????????????????????????????????ResultSet.TYPE_SCROLL_INSENSITIVE, ??
          50. ??????????????????????????????????????ResultSet.CONCUR_UPDATABLE); ??
          51. ???????ResultSet?rs?=?stmt.executeQuery( "SELECT?a,?b?FROM?TABLE2" ); ??
          52. ??????? //?rs?will?be?scrollable,?will?not?show?changes?made?by?others, ??
          53. ??????? //?and?will?be?updatable ??
          54. ?????? ??
          55. ???? 4 .ResultSet和ResultSetMetaData沒有直接提供方法返回查詢所返回的行數。然而,在JDBC ??
          56. ????  2.0 中,可以通過調用last()方法將游標定位到ResultSet的最后一行,然后調用getRow()方 ??
          57. ???? 法獲取當前的行號。在JDBC1. 0 中,確定行數的惟一方式是重復調用ResultSet的next()方法, ??
          58. ???? 直到它返回 false 為至 ??
          59. ??
          60. 八、關閉連接: ??
          61. ????在關閉數據庫連接時應該以ResultSet、Statement、Connection的順序進行 ??
          62. ??
          63. JDBC-PreparedStatement(預備語句) ??
          64. ??
          65. 一、PreparedStatement(預備語句)的創(chuàng)建: ??
          66. 首先按照標準的格式創(chuàng)建參數化語句,在實際使用之前發(fā)送參數到數據庫進行編譯。用問號表示語句中應該為具體的值所替換的位置。每次使用預備語句時,只需要使用相應的setXxx調用,替換語句中標記出來的參數。然后就可以和常規(guī)的語句一樣,使用executeQuery或execute/executeUpdate修改表中的數據。例如: ??
          67. ?//url形如:String url = "jdbc:oracle:thin:@數據庫服務器IP地址:1521:Oracle數據庫SID名字";?
          68. Connection?connection?=?DriverManager.getConnection?(url,username,password); ??
          69. //?創(chuàng)建帶問號的參數化語句 ??
          70. String?template?=? "?UPDATE?music?SET?price=??WHERE?id=??" ; ??
          71. PreparedStatement?statement?=?connection.prepareStatement?(template); ??
          72. ??
          73. float ?newPrices[]?=?getNewPrices(); ??
          74. int ?recordingIDs?=?getIDs(); ??
          75. for ( int ?i= 0 ;?i
          76. ??? //?用setXxx代替? ??
          77. ???statement.setFloat( 1 ,newPrices[i]); ??
          78. ???statement.setInt( 2 ,recordingIDs[i]); ??
          79. ??? //?執(zhí)行預備語句 ??
          80. statement.execute();} ??
          81. ??
          82. 二、使用PreparedStatement的好處: ??
          83. 1 .依賴于服務器對預編譯查詢的支持,以及驅動程序處理原始查詢的效率,預備語句在性能上的優(yōu)勢可能有很大的不同。 ??
          84. 2 .安全是預備語句的另外一個特點,我們推薦在通過HTML表單接受用戶輸入,然后對數據庫進行更新時,一定要使用預備語句或存儲過程。 ??
          85. 3 .預備語句還能夠正確地處理嵌入在字符串中的引號以及處理非字符數據(比如向數據庫發(fā)送序列化后的對象)???? ??
          86. ??
          87. JDBC-CallableStatement(可調用語句) ??
          88. ??
          89. 一、使用CallableStatement(可調用語句)的優(yōu)缺點: ??
          90. 1 .優(yōu)點:語法錯誤可以在編譯時找出來,而非在運行期間;數據庫存儲過程的運行可能比常規(guī)的 ??
          91. SQL查詢快得多;程序員只需知道輸入和輸出參數,不需了解表的結構。另外,由于數據庫語言能夠訪問數據庫本地的一下兒功能(序列,觸發(fā)器,多重游標),因此用它來編寫存儲過程可能要比使用Java編程語言要簡易一些。 ??
          92. 2 .缺點:存儲過程的商業(yè)邏輯在數據庫服務器上運行,而非客戶機或Web服務器。而行業(yè)的發(fā)展趨勢是盡可能多地將商業(yè)邏輯移出數據庫,將它們放在JavaBean組件(或者在大型的系統(tǒng)中,EnterPrise?JavaBean組件)中,在Web構架上采用這種方式的主要動機是:數據庫訪問和網絡I/O常常是性能的瓶頸。 ??
          93. ??
          94. 二、使用CallableStatement在JAVA中調用數據庫存儲過程: ??
          95. ??
          96. 1 .定義對數據庫過程的調用 ??
          97. ????A.無參數過程:{?call?procedure_name} ??
          98. ?????B.?僅有輸入參數的過程:{call?procedure_name(?,?...)} ??
          99. ????C.有一個輸出參數的過程:{??Call?procedure_name} ??
          100. ????D.既有輸入參數又有輸出參數的過程{?=call?procedure_name(?,?...)} ??
          101. ??在過程的 4 種形式中要注意過程可能返回多個輸出參數,并且參數的索引值從輸出參數開始。因此前面最后例子中,第一個輸入參數的索引值是 2 而不是 1 。 ??
          102. 2 .為過程準備CallableStatement ??
          103. ??String?procedure?=?“{???=?call?procedure_name(?,?)?}”; ??
          104. ??CallableStatement?statement?=?connection.prepareCall(procedure); ??
          105. 3 .提供輸入參數的值 ??
          106. ??在執(zhí)行存儲過程之前,我們需要調用與所要設置的項以及參數的類型相對應的setXxx,替換標記出來的輸入參數 ??
          107. ??Statement.setString( 2 ,”name”); ??
          108. 4 .注冊輸出參數的類型 ??
          109. ????我們必須使用registerOutParameter注冊每個輸出參數的JDBC類型 ??
          110. ??Statement.registerOutParameter(n,type); ??
          111. 5 .執(zhí)行這個存儲過程 ??
          112. ??Statement.execute(); ??
          113. 6 .訪問返回的輸出參數 ??
          114. ??可以通過調用getXxx訪問每個對應的輸出參數 ??
          115. ??
          116. ??
          117. ??
          118. 例如: ??
          119. Connection?connection?=?DriverManager.getConnection(url,username,password); ??
          120. String?procedure?=?“{???=?call?myProc(?,?)}”; ??
          121. CallableStatement?statement?=?connection.prepareCall(procedure); ??
          122. statement.setString( 2 ,×××); ??
          123. statement.setFloat( 3 ,×××); ??
          124. statement.registerOutParameter( 1 ,Types.INTEGER); ??
          125. statement.execute(); ??
          126. int ?row?=?statement.getInt( 1 ); ??
          127. ??
          128. JDBC-Transation(事務處理) ??
          129. ??
          130. 一、Transation(事務處理)的概念: ??
          131. 在更新數據庫時,默認情況下,更改是永久性寫入到數據庫。然而這種默認行為可以通過編寫程序來關閉。在自動交付關閉的情況下,如果在更新時發(fā)生問題,則對數據庫的每個更改都能夠取消(或者說回退到最初的值)。如果更新成功,那么之后可以將這些更改永久性提交給數據庫。這種方式也稱為事務管理。 ??
          132. 我們需要確保,要么所有的操作都發(fā)生,要么所有的操作都不發(fā)生。這就是事務管理的原則。 ??
          133. ??
          134. 二、在JAVA中使用Transation(事務管理)保證數據庫的完整性: ??
          135. 我們使用 try - catch - finally 塊來正確地應對事務管理,首先,記錄自動提交的當前狀態(tài)。然后,在 try 塊中,調用setAutoCommit( false )并執(zhí)行一系列的查詢或更新。如果發(fā)生故障,則在 catch 塊中調用rollback;如果事務成功,則在 try 塊的結尾調用commit。不管哪種方式,都在 finally 塊中重置自動提交的狀態(tài)。例如: ??
          136. ??
          137. Connection?connection?=?DriverManager.getConnection(url,username,password); ??
          138. boolean ?autoCommit?=?connection.getAutoCommit(); ??
          139. Statement?statement; ??
          140. try { ??
          141. ????connection.setAutoCommit( false );???? //?關閉數據庫的自動提交 ??
          142. ????statement?=?connection.createStatement(); ??
          143. statement.execute(…); ??
          144. statement.execute(..); ??
          145. … ??
          146. connection.commit();???????????????? //?如果所有語句執(zhí)行成功則提交事務 ??
          147. } ??
          148. catch (SQLException?sqle){ ??
          149. ????connection.rollback();???????????????? //?如果有異常發(fā)生則回滾所有的事務 ??
          150. } ??
          151. finally { ??
          152. ???? if (statement!= null ){statement.close();} ??
          153. connection.setAutoCommit(autoCommit);???? //?重置自動提交的狀態(tài) ??
          154. } ??
          155. 上面的代碼中,從DriverManager獲取連接的語句在 try / catch 塊之外。這樣除非成功獲取連接,否則不會調用rollback。如果把獲取連接的語句放在 try / catch 快之內,一旦在連接成功后發(fā)生異常,由于rollback的作用會把已經建立的連接斷開。但是getConnection方法也會拋出SQLException異常這個異常要么被外圍的方法重新拋出,要么在單獨的 try / catch 塊內捕獲。? ??
          156. JDBC的常用API ??
          157. ??
          158. 一、Connection接口: ??
          159. ???? 1 .createStatement():創(chuàng)建數據庫連接 ??
          160. ???? 2 .prepareStatement(String?sql):創(chuàng)建預處理語句 ??
          161. ???? 3 .prepareCall(String?sql):創(chuàng)建可調用語句 ??
          162. ??
          163. ???? 4 .getAutoCommit():獲取自動提交的模式 ??
          164. ???? 5 .setAutoCommit():設置自動提交的模式 ??
          165. ???? ??
          166. ???? 6 .commit():提交所執(zhí)行的SQL語句 ??
          167. ???? 7 .rollback():回滾所執(zhí)行的SQL語句 ??
          168. ??
          169. ???? 8 .getMetaData():獲取一個DatabaseMetaData對象,該對象包含了有關數據庫的基本信息 ??
          170. ??
          171. ???? 9 .close():關閉數據庫連接 ??
          172. ???? 10 .isClose():判斷數據庫連接是否超時或被顯示關閉 ??
          173. ??
          174. 二、Statement接口: ??
          175. ???? 1 .execute(String?sql):執(zhí)行SQL語句,如果返回值是結果集則為 true ,否則為 false ??
          176. ???? 2 .executeQuery(String?sql):執(zhí)行SQL語句,返回值為ResultSet ??
          177. ???? 3 .executeUpdate(String?sql):執(zhí)行SQL語句,返回值為所影響的行數 ??
          178. ???? ??
          179. ???? 4 .addBatch(String?sql):向當前Statement對象的命令列表中添加新的批處理SQL語句 ??
          180. ???? 5 .clearBatch():清空當前Statement對象的命令列表 ??
          181. ???? 6 .executeBatch():執(zhí)行當前Statement對象的批處理語句,返回值為每個語句所影響的函數數組 ??
          182. ??
          183. ???? 7 .getConnection():返回創(chuàng)建了該Statement對象的Connection對象 ??
          184. ??
          185. ???? 8 .getQueryTimeout():獲取等待處理結果的時間 ??
          186. ???? 9 .setQueryTimeout():設置等待處理結果的時間 ??
          187. ?????????? ??
          188. 三、ResultSet接口:???? ??
          189. ???? 1 .first()/beforeFirst():將游標移動到ResultSet中第一條記錄(的前面) ??
          190. ???? 2 .last()/afterLast():將游標移動到ResultSet中最后一條記錄(的后面) ??
          191. ??
          192. ???? 3 .absolute( int ?column):將游標移動到相對于第一行的指定行,負數則為相對于最后一條記錄 ??
          193. ???? 4 .relative( int ?rows):將游標移動到相對于當前行的第幾行,正為向下,負為向上 ??
          194. ??
          195. ???? 5 .next():將游標下移一行 ??
          196. ???? 6 .previous():將游標上移一行 ??
          197. ??
          198. ???? 7 .insertRow():向當前ResultSet和數據庫中被插入行處插入一條記錄 ??
          199. ???? 8 .deleteRow():將當前ResultSet中的當前行和數據庫中對應的記錄刪除 ??
          200. ???? 9 .updateRow():用當前ResultSet中已更新的記錄更新數據庫中對應的記錄 ??
          201. ???? 10 .cancelUpdate():取消當前對ResultSet和數據庫中所做的操作 ??
          202. ??
          203. ???? 11 .findColumn(String?columnName):返回當前ResultSet中與指定列名對應的索引 ??
          204. ??
          205. ???? 12 .getRow():返回ResultSet中的當前行號 ??
          206. ??
          207. ???? 13 .refreshRow():更新當前ResultSet中的所有記錄 ??
          208. ??
          209. ???? 14 .getMetaData():返回描述ResultSet的ResultSetMetaData對象 ??
          210. ??
          211. ???? 15 .isAfterLast():?是否到了結尾 ??
          212. ???? 16 .isBeforeFirst():?是否到了開頭 ??
          213. ???? 17 .isFirst():是否第一條記錄??? ??
          214. ???? 18 .isLast():?是否最后一條記錄 ??
          215. ??
          216. ???? 19 .wasNull():檢查列值是否為NULL值,如果列的類型為基本類型,且數據庫中的值為 0 ,那么 ??
          217. 這項檢查就很重要。由于數據庫NULL也返回 0 ,所以 0 值和數據庫的NULL不能區(qū)分。如果列的類型為對象,可以簡單地將返回值與 null 比較 ??
          218. ???? ??
          219. 20 .close():關閉當前ResultSet ??
          220. ??
          221. 四、ResultSetMetaData接口: ??
          222. ???? 1 .getColumnCount():返回ResultSet中列的數目 ??
          223. ???? 2 .getColumnName():返回列在數據庫中的名稱 ??
          224. ???? 3 .getColumnType():返回列的SQL類型 ??
          225. ??
          226. ???? 4 .isReadOnly():表示該數據項是否為只讀值 ??
          227. ???? 5 .isNullable():表示該列是否可以存儲NULL ??
          228. ??
          229. ??
          230. ??
          231. 基于JDBC的數據庫連接池技術研究與應用 ??
          232.    ??
          233. Java應用程序訪問數據庫的基本原理? ??
          234. ??
          235. 在Java語言中,JDBC(Java?DataBase?Connection)是應用程序與數據庫溝通的橋梁,?即Java語言通過JDBC技術訪問數據庫。JDBC是一種“開放”的方案,它為數據庫應用開發(fā)人員、數據庫前臺工具開發(fā)人員提供了一種標準的應用程序設計接口,使開發(fā)人員可以用純Java語言編寫完整的數據庫應用程序。JDBC提供兩種API,分別是面向開發(fā)人員的API和面向底層的JDBC驅動程序API,底層主要通過直接的JDBC驅動和JDBC-ODBC橋驅動實現與數據庫的連接。? ??
          236. ??
          237. 一般來說,Java應用程序訪問數據庫的過程(如圖 1 所示)是:? ??
          238.  ①裝載數據庫驅動程序;? ??
          239.  ②通過JDBC建立數據庫連接;? ??
          240.  ③訪問數據庫,執(zhí)行SQL語句;? ??
          241.  ④斷開數據庫連接。? ??
          242. ? ??
          243. JDBC作為一種數據庫訪問技術,具有簡單易用的優(yōu)點。但使用這種模式進行Web應用程序開發(fā),存在很多問題:首先,每一次Web請求都要建立一次數據庫連接。建立連接是一個費時的活動,每次都得花費 0 .05s~1s的時間,而且系統(tǒng)還要分配內存資源。這個時間對于一次或幾次數據庫操作,或許感覺不出系統(tǒng)有多大的開銷。可是對于現在的Web應用,尤其是大型電子商務網站,同時有幾百人甚至幾千人在線是很正常的事。在這種情況下,頻繁的進行數據庫連接操作勢必占用很多的系統(tǒng)資源,網站的響應速度必定下降,嚴重的甚至會造成服務器的崩潰。不是危言聳聽,這就是制約某些電子商務網站發(fā)展的技術瓶頸問題。其次,對于每一次數據庫連接,使用完后都得斷開。否則,如果程序出現異常而未能關閉,將會導致數據庫系統(tǒng)中的內存泄漏,最終將不得不重啟數據庫。還有,這種開發(fā)不能控制被創(chuàng)建的連接對象數,系統(tǒng)資源會被毫無顧及的分配出去,如連接過多,也可能導致內存泄漏,服務器崩潰。? ??
          244. ??
          245. 數據庫連接池(connection?pool)的工作原理? ??
          246. ??
          247. 1 、基本概念及原理? ??
          248. ??
          249. 數據庫連接池的基本思想就是為數據庫連接建立一個“緩沖池”。預先在緩沖池中放入一定數量的連接,當需要建立數據庫連接時,只需從“緩沖池”中取出一個,使用完畢之后再放回去。我們可以通過設定連接池最大連接數來防止系統(tǒng)無盡的與數據庫連接。更為重要的是我們可以通過連接池的管理機制監(jiān)視數據庫的連接的數量、使用情況,為系統(tǒng)開發(fā)、測試及性能調整提供依據。? ??
          250. ??
          251. 2 、服務器自帶的連接池? ??
          252. ??
          253. JDBC的API中沒有提供連接池的方法。一些大型的WEB應用服務器如BEA的WebLogic和IBM的WebSphere等提供了連接池的機制,但是必須有其第三方的專用類方法支持連接池的用法。? ??
          254. ??
          255. 連接池關鍵問題分析? ??
          256. ??
          257. 1 、并發(fā)問題? ??
          258. ??
          259. 為了使連接管理服務具有最大的通用性,必須考慮多線程環(huán)境,即并發(fā)問題。這個問題相對比較好解決,因為Java語言自身提供了對并發(fā)管理的支持,使用 synchronized 關鍵字即可確保線程是同步的。使用方法為直接在類方法前面加上 synchronized 關鍵字,如:? ??
          260. public ? synchronized ?Connection?getConnection()?? ??
          261. ??
          262. 2 、多數據庫服務器和多用戶? ??
          263. ??
          264. 對于大型的企業(yè)級應用,常常需要同時連接不同的數據庫(如連接Oracle和Sybase)。如何連接不同的數據庫呢?我們采用的策略是:設計一個符合單例模式的連接池管理類,在連接池管理類的唯一實例被創(chuàng)建時讀取一個資源文件,其中資源文件中存放著多個數據庫的url地址()、用戶名()、密碼()等信息。如tx.url= 172.21 . 15.123 5000 /tx_it,tx.user=yang,tx.password=yang321。根據資源文件提供的信息,創(chuàng)建多個連接池類的實例,每一個實例都是一個特定數據庫的連接池。連接池管理類實例為每個連接池實例取一個名字,通過不同的名字來管理不同的連接池。? ??
          265. ??
          266. 對于同一個數據庫有多個用戶使用不同的名稱和密碼訪問的情況,也可以通過資源文件處理,即在資源文件中設置多個具有相同url地址,但具有不同用戶名和密碼的數據庫連接信息。? ??
          267. ??
          268. 3 、事務處理? ??
          269. ??
          270. 我們知道,事務具有原子性,此時要求對數據庫的操作符合“ALL-ALL-NOTHING”原則,即對于一組SQL語句要么全做,要么全不做。? ??
          271. ??
          272. 在Java語言中,Connection類本身提供了對事務的支持,可以通過設置Connection的AutoCommit屬性為 false ,然后顯式的調用commit或rollback方法來實現。但要高效的進行Connection復用,就必須提供相應的事務支持機制。可采用每一個事務獨占一個連接來實現,這種方法可以大大降低事務管理的復雜性。? ??
          273. ??
          274. 4 、連接池的分配與釋放? ??
          275. ??
          276. 連接池的分配與釋放,對系統(tǒng)的性能有很大的影響。合理的分配與釋放,可以提高連接的復用度,從而降低建立新連接的開銷,同時還可以加快用戶的訪問速度。? ??
          277. ??
          278. 對于連接的管理可使用空閑池。即把已經創(chuàng)建但尚未分配出去的連接按創(chuàng)建時間存放到一個空閑池中。每當用戶請求一個連接時,系統(tǒng)首先檢查空閑池內有沒有空閑連接。如果有就把建立時間最長(通過容器的順序存放實現)的那個連接分配給他(實際是先做連接是否有效的判斷,如果可用就分配給用戶,如不可用就把這個連接從空閑池刪掉,重新檢測空閑池是否還有連接);如果沒有則檢查當前所開連接池是否達到連接池所允許的最大連接數(maxConn),如果沒有達到,就新建一個連接,如果已經達到,就等待一定的時間(timeout)。如果在等待的時間內有連接被釋放出來就可以把這個連接分配給等待的用戶,如果等待時間超過預定時間timeout,則返回空值( null )。系統(tǒng)對已經分配出去正在使用的連接只做計數,當使用完后再返還給空閑池。對于空閑連接的狀態(tài),可開辟專門的線程定時檢測,這樣會花費一定的系統(tǒng)開銷,但可以保證較快的響應速度。也可采取不開辟專門線程,只是在分配前檢測的方法。? ??
          279. ??
          280. 5 、連接池的配置與維護? ??
          281. ??
          282. 連接池中到底應該放置多少連接,才能使系統(tǒng)的性能最佳?系統(tǒng)可采取設置最小連接數(minConn)和最大連接數(maxConn)來控制連接池中的連接。最小連接數是系統(tǒng)啟動時連接池所創(chuàng)建的連接數。如果創(chuàng)建過多,則系統(tǒng)啟動就慢,但創(chuàng)建后系統(tǒng)的響應速度會很快;如果創(chuàng)建過少,則系統(tǒng)啟動的很快,響應起來卻慢。 ??
          283. 可以在開發(fā)時,設置較小的最小連接數,開發(fā)起來會快,而在系統(tǒng)實際使用時設置較大的,因為這樣對訪問客戶來說速度會快些。最大連接數是連接池中允許連接的最大數目,具體設置多少,要看系統(tǒng)的訪問量,可通過反復測試,找到最佳點。? ??
          284. ??
          285. 如何確保連接池中的最小連接數呢?有動態(tài)和靜態(tài)兩種策略。動態(tài)即每隔一定時間就對連接池進行檢測,如果發(fā)現連接數量小于最小連接數,則補充相應數量的新連接,以保證連接池的正常運轉。靜態(tài)是發(fā)現空閑連接不夠時再去檢查。? ??
          286. ??
          287. 連接池的實現? ??
          288. ??
          289. 1 、連接池模型? ??
          290. ??
          291. 連接池類是對某一數據庫所有連接的“緩沖池”,主要實現以下功能:①從連接池獲取或創(chuàng)建可用連接;②使用完畢之后,把連接返還給連接池;③在系統(tǒng)關閉前,斷開所有連接并釋放連接占用的系統(tǒng)資源;④還能夠處理無效連接(原來登記為可用的連接,由于某種原因不再可用,如超時,通訊問題),并能夠限制連接池中的連接總數不低于某個預定值和不超過某個預定值。? ??
          292. ??
          293. 連接池管理類是連接池類的外覆類(wrapper),符合單例模式,即系統(tǒng)中只能有一個連接池管理類的實例。其主要用于對多個連接池對象的管理,具有以下功能:①裝載并注冊特定數據庫的JDBC驅動程序;②根據屬性文件給定的信息,創(chuàng)建連接池對象;③為方便管理多個連接池對象,為每一個連接池對象取一個名字,實現連接池名字與其實例之間的映射;④跟蹤客戶使用連接情況,以便需要是關閉連接釋放資源。連接池管理類的引入主要是為了方便對多個連接池的使用和管理,如系統(tǒng)需要連接不同的數據庫,或連接相同的數據庫但由于安全性問題,需要不同的用戶使用不同的名稱和密碼。? ??
          294. ??
          295. 2 、連接池實現? ??
          296. ??
          297. 下面給出連接池類和連接池管理類的主要屬性及所要實現的基本接口:? ??
          298. ??
          299. public ? class ?DBConnectionPool? implements ?TimerListener{? ??
          300. ??
          301. private ? int ?checkedOut; //已被分配出去的連接數? ??
          302. private ?ArrayList?freeConnections?=? new ?ArrayList(); //容器,空閑池,根據創(chuàng)建時間順序存放已創(chuàng)建 ??
          303. 尚未分配出去的連接? ??
          304. private ? int ?minConn; //連接池里連接的最小數量? ??
          305. private ? int ?maxConn; //連接池里允許存在的最大連接數? ??
          306. private ?String?name; //為這個連接池取個名字,方便管理? ??
          307. private ?String?password; //連接數據庫時需要的密碼? ??
          308. private ?String?url; //所要創(chuàng)建連接的數據庫的地址? ??
          309. private ?String?user; //連接數據庫時需要的用戶名? ??
          310. public ?Timer?timer; //定時器? ??
          311. ??
          312. public ?DBConnectionPool(String?name,?String?URL,?String?user,?Stringpassword,? int ?maxConn)? ??
          313. public ? synchronized ? void ?freeConnection(Connection?con)? //使用完畢之后把連接返還給空閑池? ??
          314. public ? synchronized ?Connection?getConnection( long ?timeout) //得到一個連接,timeout是等待時間? ??
          315. public ? synchronized ? void ?release() //斷開所有連接,釋放占用的系統(tǒng)資源? ??
          316. private ?Connection?newConnection() //新建一個數據庫連接? ??
          317. public ? synchronized ? void ?TimerEvent()? //定時器事件處理函數? ??
          318. } ??
          319. ??
          320. public ? class ?DBConnectionManager?{? ??
          321. ??
          322. static ? private ?DBConnectionManager?instance; //連接池管理類的唯一實例? ??
          323. static ? private ? int ?clients; //客戶數量? ??
          324. private ?ArrayList?drivers?=? new ?ArrayList(); //容器,存放數據庫驅動程序? ??
          325. private ?HashMap?pools?=? new ?HashMap?(); //以name/value的形式存取連接池對象的名字及連接池對象? ??
          326. ??
          327. private ? void ?loadDrivers(Properties?props) //裝載數據庫驅動程序? ??
          328. private ? void ?createPools(Properties?props) //根據屬性文件提供的信息,創(chuàng)建一個或多個連接池? ??
          329. ??
          330. private ?DBConnectionManager() //私有構造函數,在其中調用初始化函數init()? ??
          331. private ? void ?init() //初始化連接池管理類的唯一實例,由私有構造函數調用? ??
          332. static ? synchronized ? public ?DBConnectionManager?getInstance() //如果唯一的實例instance已經創(chuàng)建,直接返回這個實例;否則,調用私有構造函數,創(chuàng)建連接池管理類的唯一實例? ??
          333. ??
          334. public ?Connection?getConnection(String?name) //從名字為name的連接池對象//中得到一個連接? ??
          335. public ?Connection?getConnection(String?name,? long ?time) //從名字為name?的連接池對象中取得一個連接,time是等待時間? ??
          336. ??
          337. public ? void ?freeConnection(String?name,?Connection?con) //釋放一個連接name是一個連接池對象的名? ??
          338. public ? synchronized ? void ?release() //釋放所有資源? ??
          339. ??
          340. }??? ??
          341. ??
          342. 3 、連接池使用? ??
          343. ??
          344. 上面所實現的連接池在程序開發(fā)時如何應用到系統(tǒng)中呢?下面以Servlet為例說明連接池的使用。? ??
          345. Servlet的生命周期是:在開始建立servlet時,調用其初始化(init)方法。之后每個用戶請求都導致一個調用前面建立的實例的service方法的線程。最后,當服務器決定卸載一個servlet時,它首先調用該servlet的?destroy方法。?根據servlet的特點,我們可以在初始化函數中生成連接池管理類的唯一實例(其中包括創(chuàng)建一個或多個連接池)。如:? ??
          346. ??
          347. public ? void ?init()? throws ?ServletException? ??
          348. {? ??
          349. ?? //?getInstance()?DBConnectionManager()?init() ??
          350.  connMgr?=?DBConnectionManager.getInstance();?? ??
          351. }??? ??
          352. ??
          353. 然后就可以在service方法中通過連接池名稱使用連接池,執(zhí)行數據庫操作。最后在destroy方法中釋放占用的系統(tǒng)資源,如:?? ??
          354. ??
          355. public ? void ?destroy()?{?? ??
          356. connMgr.release();? ??
          357. super .destroy();?? ??
          358. }??

          posted on 2007-09-20 19:54 李云澤 閱讀(393) 評論(0)  編輯  收藏 所屬分類: J2EE

          主站蜘蛛池模板: 张家川| 东阿县| 新昌县| 中卫市| 建瓯市| 西乌| 丹棱县| 手游| 三河市| 鹤庆县| 威海市| 民乐县| 本溪市| 新干县| 肥东县| 文登市| 抚州市| 绥宁县| 巨野县| 焦作市| 新野县| 东乌珠穆沁旗| 宜兴市| 盐山县| 北流市| 禄丰县| 雷州市| 永登县| 枞阳县| 连山| 齐河县| 游戏| 任丘市| 理塘县| 西贡区| 临江市| 万载县| 青田县| 洛宁县| 凤阳县| 太康县|