Spring源碼解析三
《Spring源碼解析三》由會員分享,可在線閱讀,更多相關(guān)《Spring源碼解析三(18頁珍藏版)》請?jiān)谘b配圖網(wǎng)上搜索。
1、 下面我們看看Spring JDBC相關(guān)的實(shí)現(xiàn),? 在Spring中,JdbcTemplate是經(jīng)常被使用的類來幫助用戶程序操作數(shù)據(jù)庫,在JdbcTemplate為用戶程序提供了許多便利的數(shù)據(jù)庫操作方法,比如查詢,更新等,而且在Spring中,有許多類似 JdbcTemplate的模板,比如HibernateTemplate等等 – 看來這是Rod.Johnson的慣用手法,一般而言這種Template中都是通過回調(diào)函數(shù)CallBack類的使用來完成功能的,客戶需要在回調(diào)接口中實(shí)現(xiàn)自己需要的定制行為,比如使用客戶想要用的SQL語句等。不過往往Spring通過這種回調(diào)函數(shù)的實(shí)現(xiàn)已經(jīng)為我們提供
2、了許多現(xiàn)成的方法供客戶使用。一般來說回調(diào)函數(shù)的用法采用匿名類的方式來實(shí)現(xiàn),比如:? ? 如轉(zhuǎn)載請注明,轉(zhuǎn)載自:關(guān)注Java[] 本文鏈接:?Spring源代碼分析(三):Spring JDBC Java代碼? 1. JdbcTemplate?=?new?JdbcTemplate(datasource); ?? 2. jdbcTemplate.execute(new?CallBack(){ ?? 3. ????????????public?CallbackInterfacedoInAction(){ ?? 4. ???????????????…… ?? 5. ?????????
3、??????//用戶定義的代碼或者說Spring替我們實(shí)現(xiàn)的代碼??? 6. ????????????} ?? 推薦精選 7. }?? 在模板中嵌入的是需要客戶化的代碼,由Spring來作或者需要客戶程序親自動手完成。下面讓我們具體看看在JdbcTemplate中的代碼是怎樣完成使命的,我們舉JdbcTemplate.execute()為例,這個方法是在JdbcTemplate中被其他方法調(diào)用的基本方法之一,客戶程序往往用這個方法來執(zhí)行基本的SQL語句:? ? Java代碼? 1. public?Object?execute(ConnectionCallback?action
4、)?throws?DataAccessException?{ ?? 2. ????//這里得到數(shù)據(jù)庫聯(lián)接??? 3. ????Connection?con?=?DataSourceUtils.getConnection(getDataSource()); ?? 4. ????try?{ ?? 5. ????????Connection?conToUse?=?con; ?? 6. ????????//有些特殊的數(shù)據(jù)庫,需要我們使用特別的方法取得datasource??? 7. ????????if?(this.nativeJdbcExtractor?!=?null)?{ ?? 8.
5、 ????????????//?Extract?native?JDBC?Connection,?castable?to?OracleConnection?or?the?like.??? 推薦精選 9. ????????????conToUse?=?this.nativeJdbcExtractor.getNativeConnection(con); ?? 10. ????????} ?? 11. ????????else?{ ?? 12. ????????????//?Create?close-suppressing?Connection?proxy,?also?preparing
6、?returned?Statements.??? 13. ????????????conToUse?=?createConnectionProxy(con); ?? 14. ????????} ?? 15. ????//這里調(diào)用的是傳遞進(jìn)來的匿名類的方法,也就是用戶程序需要實(shí)現(xiàn)CallBack接口的地方。??? 16. ????????return?action.doInConnection(conToUse); ?? 17. ????} ?? 18. ????catch?(SQLException?ex)?{ ?? 19. ????????//如果捕捉到數(shù)據(jù)庫異常,把數(shù)據(jù)庫聯(lián)接
7、釋放,同時拋出一個經(jīng)過Spring轉(zhuǎn)換過的Spring數(shù)據(jù)庫異常,??? 20. ????????//我們知道,Spring做了一個有意義的工作是把這些數(shù)據(jù)庫異常統(tǒng)一到自己的異常體系里了。??? 21. ????????DataSourceUtils.releaseConnection(con,?getDataSource()); ?? 22. ????????con?=?null; ?? 推薦精選 23. ????????throw?getExceptionTranslator().translate("ConnectionCallback",?getSql(action),?
8、ex); ?? 24. ????} ?? 25. ????finally?{ ?? 26. ????????//最后不管怎樣都會把數(shù)據(jù)庫連接釋放??? 27. ????????DataSourceUtils.releaseConnection(con,?getDataSource()); ?? 28. ????} ?? 29. }?? 對于JdbcTemplate中給出的其他方法,比如query,update,execute等的實(shí)現(xiàn),我們看看query():? ? Java代碼? 1. public?Object?query(PreparedStatementCreator
9、?psc,?final?PreparedStatementSetter?pss,?final?ResultSetExtractor?rse) ?? 2. ????????throws?DataAccessException?{ ?? 3. ????………. ?? 4. ????//這里調(diào)用了我們上面看到的execute()基本方法,然而這里的回調(diào)實(shí)現(xiàn)是Spring為我們完成的查詢過程??? 推薦精選 5. ????return?execute(psc,?new?PreparedStatementCallback()?{ ?? 6. ????????public?Object?d
10、oInPreparedStatement(PreparedStatement?ps)?throws?SQLException?{ ?? 7. ????????????//準(zhǔn)備查詢結(jié)果集??? 8. ????????????ResultSet?rs?=?null; ?? 9. ????????????try?{ ?? 10. ????????????//這里配置SQL參數(shù)??? 11. ????????????????if?(pss?!=?null)?{ ?? 12. ????????????????????pss.setValues(ps); ?? 13. ???????????
11、?????} ?? 14. ??????????//這里執(zhí)行的SQL查詢??? 15. ????????????????rs?=?ps.executeQuery(); ?? 16. ????????????????ResultSet?rsToUse?=?rs; ?? 17. ????????????????if?(nativeJdbcExtractor?!=?null)?{ ?? 18. ????????????????????rsToUse?=?nativeJdbcExtractor.getNativeResultSet(rs); ?? 19. ????????????????}
12、 ?? 20. ?????????//返回需要的記錄集合??? 21. ????????????????return?rse.extractData(rsToUse); ?? 22. ????????????} ?? 23. ????????????finally?{ ?? 推薦精選 24. ????????//最后關(guān)閉查詢的紀(jì)錄集,對數(shù)據(jù)庫連接的釋放在execute()中釋放,就像我們在上面分析的看到那樣。??? 25. ????????????????JdbcUtils.closeResultSet(rs); ?? 26. ????????????????if?(pss
13、?instanceof?ParameterDisposer)?{ ?? 27. ????????????????????((ParameterDisposer)?pss).cleanupParameters(); ?? 28. ????????????????} ?? 29. ????????????} ?? 30. ????????} ?? 31. ????}); ?? 32. }?? 輔助類DataSourceUtils來用來對數(shù)據(jù)庫連接進(jìn)行管理的主要工具,比如打開和關(guān)閉數(shù)據(jù)庫連接等基本操作:? ? Java代碼? 1. public?static?Connection
14、?doGetConnection(DataSource?dataSource)?throws?SQLException?{ ?? 2. ???//把對數(shù)據(jù)庫連接放到事務(wù)管理里面進(jìn)行管理??? 3. ????ConnectionHolder?conHolder?=?(ConnectionHolder)?TransactionSynchronizationManager.getResource(dataSource); ?? 推薦精選 4. ????if?(conHolder?!=?null?&&?(conHolder.hasConnection()?||?conHolder.isSy
15、nchronizedWithTransaction()))?{ ?? 5. ????????conHolder.requested(); ?? 6. ????????if?(!conHolder.hasConnection())?{ ?? 7. ????????????logger.debug("Fetching?resumed?JDBC?Connection?from?DataSource"); ?? 8. ????????????conHolder.setConnection(dataSource.getConnection()); ?? 9. ????????} ?? 10.
16、 ????????return?conHolder.getConnection(); ?? 11. ????} ?? 12. ????//?這里得到需要的數(shù)據(jù)庫連接,在配置文件中定義好的。??? 13. ????logger.debug("Fetching?JDBC?Connection?from?DataSource"); ?? 14. ????Connection?con?=?dataSource.getConnection(); ?? 15. ?? 16. ????if?(TransactionSynchronizationManager.isSynchronizationA
17、ctive())?{ ?? 17. ????????logger.debug("Registering?transaction?synchronization?for?JDBC?Connection"); ?? 18. ????????//?Use?same?Connection?for?further?JDBC?actions?within?the?transaction.??? 推薦精選 19. ????????//?Thread-bound?object?will?get?removed?by?synchronization?at?transaction?completion
18、.??? 20. ????????ConnectionHolder?holderToUse?=?conHolder; ?? 21. ????????if?(holderToUse?==?null)?{ ?? 22. ????????????holderToUse?=?new?ConnectionHolder(con); ?? 23. ????????} ?? 24. ????????else?{ ?? 25. ????????????holderToUse.setConnection(con); ?? 26. ????????} ?? 27. ????????holderToU
19、se.requested(); ?? 28. ????????TransactionSynchronizationManager.registerSynchronization( ?? 29. ????????????????new?ConnectionSynchronization(holderToUse,?dataSource)); ?? 30. ????????holderToUse.setSynchronizedWithTransaction(true); ?? 31. ????????if?(holderToUse?!=?conHolder)?{ ?? 32. ??????
20、??????TransactionSynchronizationManager.bindResource(dataSource,?holderToUse); ?? 33. ????????} ?? 34. ????} ?? 推薦精選 35. ?? 36. ????return?con; ?? 37. }?? 那我們實(shí)際的DataSource對象是怎樣得到的?很清楚我們需要在上下文中進(jìn)行配置:它作為JdbcTemplate父類JdbcAccessor的屬性存在:? ? Java代碼? 1. public?abstract?class?JdbcAccessor?implem
21、ents?InitializingBean?{ ?? 2. ?? 3. ????/**?這里是我們依賴注入數(shù)據(jù)庫數(shù)據(jù)源的地方。?*/?? 4. ????private?DataSource?dataSource; ?? 5. ?? 6. ????/**?Helper?to?translate?SQL?exceptions?to?DataAccessExceptions?*/?? 7. ????private?SQLExceptionTranslator?exceptionTranslator; ?? 8. ?? 9. ????private?boolean?lazyInit?=
22、?true; ?? 10. ?? 11. ????…….. ?? 推薦精選 12. }?? 而對于DataSource的緩沖池實(shí)現(xiàn),我們通過定義Apache Jakarta Commons DBCP或者C3P0提供的DataSource來完成,然后只要在上下文中配置好就可以使用了。從上面我們看到JdbcTemplate提供了許多簡單查詢和更新功能,但是如果需要更高層次的抽象,以及更面向?qū)ο蟮姆椒▉碓L問數(shù)據(jù)庫。Spring為我們提供了 org.springframework.jdbc.object包,這里面包含了SqlQuery,SqlMappingQuery, SqlUpdate
23、和StoredProcedure等類,這些類都是Spring JDBC應(yīng)用程序可以使用的主要類,但我們要注意使用這些類的時候,用戶需要為他們配置好一個JdbcTemplate作為其基本的操作的實(shí)現(xiàn)。? 比如說我們使用MappingSqlQuery來將表數(shù)據(jù)直接映射到一個對象集合 – 具體可以參考書中的例子? 1.我們需要建立DataSource和sql語句并建立持有這些對象的MappingSqlQuery對象? 2.然后我們需要定義傳遞的SqlParameter,具體的實(shí)現(xiàn)我們在MappingSqlQuery的父類RdbmsOperation中可以找到:? ? Java代碼? 1.
24、 public?void?declareParameter(SqlParameter?param)?throws?InvalidDataAccessApiUsageException?{ ?? 推薦精選 2. ???//如果聲明已經(jīng)被編譯過,則該聲明無效??? 3. ???if?(isCompiled())?{ ?? 4. ???????throw?new?InvalidDataAccessApiUsageException("Cannot?add?parameters?once?query?is?compiled"); ?? 5. ???} ?? 6. ???//這里對參數(shù)值
25、進(jìn)行聲明定義??? 7. ???this.declaredParameters.add(param); ?? 而這個declareParameters維護(hù)的是一個列表:? ? Java代碼? 1. /**?List?of?SqlParameter?objects?*/?? 2. private?List?declaredParameters?=?new?LinkedList();?? 這個列表在以后compile的過程中會被使用。? 3.然后用戶程序需要實(shí)現(xiàn)MappingSqlQuery的mapRow接口,將具體的ResultSet數(shù)據(jù)生成我們需要的對象,這是我們迭代使用的方法
26、。1,2,3步實(shí)際上為我們定義好了一個迭代的基本單元作為操作模板。? 4.在應(yīng)用程序,我們直接調(diào)用execute()方法得到我們需要的對象列表,列表中的每一個對象的數(shù)據(jù)來自于執(zhí)行SQL語句得到記錄集的每一條記錄,事實(shí)上執(zhí)行的execute 推薦精選 在父類SqlQuery中起作用:? ? Java代碼? 1. public?List?executeByNamedParam(Map?paramMap,?Map?context)?throws?DataAccessException?{ ?? 2. ????validateNamedParameters(paramMap); ??
27、 3. ????Object[]?parameters?=?NamedParameterUtils.buildValueArray(getSql(),?paramMap); ?? 4. ????RowMapper?rowMapper?=?newRowMapper(parameters,?context); ?? 5. ????String?sqlToUse?=?NamedParameterUtils.substituteNamedParameters(getSql(),?new?MapSqlParameterSource(paramMap)); ?? 6. ????//我們又看到了Jd
28、bcTemplate,這里使用JdbcTemplate來完成對數(shù)據(jù)庫的查詢操作,所以我們說JdbcTemplate是基本的操作類。??? 7. ?????return?getJdbcTemplate().query(newPreparedStatementCreator(sqlToUse,?parameters),?rowMapper); ?? 8. }?? 在這里我們可以看到template模式的精彩應(yīng)用和對JdbcTemplate的靈活使用。通過使用它,我們免去了手工迭代ResultSet并將其中的數(shù)據(jù)轉(zhuǎn)化為對象列表的重復(fù)過程。在這里我們只需要定義SQL語句和 推薦精選 Sq
29、lParameter – 如果需要的話,往往SQL語句就常常能夠滿足我們的要求了。這是靈活使用JdbcTemplate的一個很好的例子。? Spring還為其他數(shù)據(jù)庫操作提供了許多服務(wù),比如使用SqlUpdate插入和更新數(shù)據(jù)庫,使用UpdatableSqlQuery更新ResultSet,生成主鍵,調(diào)用存儲過程等。? 書中還給出了對BLOB數(shù)據(jù)和CLOB數(shù)據(jù)進(jìn)行數(shù)據(jù)庫操作的例子:? 對BLOB數(shù)據(jù)的操作通過LobHander來完成,通過調(diào)用JdbcTemplate和RDBMS都可以進(jìn)行操作:? 在JdbcTemplate中,具體的調(diào)用可以參考書中的例子 – 是通過以下調(diào)用起作用的:?
30、 ? Java代碼? 1. public?Object?execute(String?sql,?PreparedStatementCallback?action)?throws?DataAccessException?{ ?? 2. ????return?execute(new?SimplePreparedStatementCreator(sql),?action); ?? 3. }?? 然后通過對實(shí)現(xiàn)PreparedStatementCallback接口的AbstractLobCreatingPreparedStatementCallback的回調(diào)函數(shù)來完成:? 推薦精選
31、 ? Java代碼? 1. public?final?Object?doInPreparedStatement(PreparedStatement?ps)?throws?SQLException,?DataAccessException?{ ?? 2. ????LobCreator?lobCreator?=?this.lobHandler.getLobCreator(); ?? 3. ????try?{ ?? 4. ????????//這是一個模板方法,具體需要由客戶程序?qū)崿F(xiàn)??? 5. ????????setValues(ps,?lobCreator); ?? 6. ???
32、?????return?new?Integer(ps.executeUpdate()); ? 7. ????} ?? 8. ????finally?{ ?? 9. ????????lobCreator.close(); ?? 10. ????} ?? 11. } ?? 12. //定義的需要客戶程序?qū)崿F(xiàn)的虛函數(shù)??? 13. protected?abstract?void?setValues(PreparedStatement?ps,?LobCreator?lobCreator) ?? 14. ????????throws?SQLException,?DataAccessExc
33、eption;?? 推薦精選 而我們注意到setValues()是一個需要實(shí)現(xiàn)的抽象方法,應(yīng)用程序通過實(shí)現(xiàn)setValues來定義自己的操作 – 在setValues中調(diào)用lobCreator.setBlobAsBinaryStrem()。讓我們看看具體的BLOB操作在LobCreator 是怎樣完成的,我們一般使用DefaultLobCreator作為BLOB操作的驅(qū)動:? ? Java代碼? 1. public?void?setBlobAsBinaryStream( ?? 2. ????????PreparedStatement?ps,?int?paramIndex,?In
34、putStream?binaryStream,?int?contentLength) ?? 3. ????????throws?SQLException?{ ?? 4. ????//通過JDBC來完成對BLOB數(shù)據(jù)的操作,對Oracle,Spring提供了OracleLobHandler來支持BLOB操作。??? 5. ????ps.setBinaryStream(paramIndex,?binaryStream,?contentLength); ?? 6. ????…….. ?? 7. }?? 上面提到的是零零碎碎的Spring JDBC使用的例子,可以看到使用Spring JD
35、BC可以幫助我們完成許多數(shù)據(jù)庫的操作。Spring對數(shù)據(jù)庫操作最基本的服務(wù)是通過JdbcTeamplate和他常用的回調(diào)函數(shù)來實(shí)現(xiàn)的,在此之上,又提供了許多RMDB的操作來幫助我們更便利的對數(shù)據(jù)庫的數(shù)據(jù)進(jìn)行操作 – 注意這里沒有引入向Hibernate這樣的O/R方案。對這些O/R方案的支持,Spring由其他包來完成服務(wù)。? 推薦精選 書中還提到關(guān)于execute和update方法之間的區(qū)別,update方法返回的是受影響的記錄數(shù)目的一個計(jì)數(shù),并且如果傳入?yún)?shù)的話,使用的是 java.sql.PreparedStatement,而execute方法總是使用 java.sql.Statement,不接受參數(shù),而且他不返回受影響記錄的計(jì)數(shù),更適合于創(chuàng)建和丟棄表的語句,而update方法更適合于插入,更新和刪除操作,這也是我們在使用時需要注意的。 (注:可編輯下載,若有不當(dāng)之處,請指正,謝謝!) 推薦精選
- 溫馨提示:
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)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 市教育局冬季運(yùn)動會安全工作預(yù)案
- 2024年秋季《思想道德與法治》大作業(yè)及答案3套試卷
- 2024年教師年度考核表個人工作總結(jié)(可編輯)
- 2024年xx村兩委涉案資金退還保證書
- 2024年憲法宣傳周活動總結(jié)+在機(jī)關(guān)“弘揚(yáng)憲法精神推動發(fā)改工作高質(zhì)量發(fā)展”專題宣講報(bào)告會上的講話
- 2024年XX村合作社年報(bào)總結(jié)
- 2024-2025年秋季第一學(xué)期初中歷史上冊教研組工作總結(jié)
- 2024年小學(xué)高級教師年終工作總結(jié)匯報(bào)
- 2024-2025年秋季第一學(xué)期初中物理上冊教研組工作總結(jié)
- 2024年xx鎮(zhèn)交通年度總結(jié)
- 2024-2025年秋季第一學(xué)期小學(xué)語文教師工作總結(jié)
- 2024年XX村陳規(guī)陋習(xí)整治報(bào)告
- 2025年學(xué)校元旦迎新盛典活動策劃方案
- 2024年學(xué)校周邊安全隱患自查報(bào)告
- 2024年XX鎮(zhèn)農(nóng)村規(guī)劃管控述職報(bào)告