亚洲国产日韩欧美一区二区三区,精品亚洲国产成人av在线,国产99视频精品免视看7,99国产精品久久久久久久成人热,欧美日韩亚洲国产综合乱

目錄 搜索
前言 簡(jiǎn)介 概覽 使用場(chǎng)景 Spring 2.0和 2.5的新特性 簡(jiǎn)介 控制反轉(zhuǎn)(IoC)容器 新的bean作用域 更簡(jiǎn)單的XML配置 可擴(kuò)展的XML編寫(xiě) Annotation(注解)驅(qū)動(dòng)配置 在classpath中自動(dòng)搜索組件 面向切面編程(AOP) 更加簡(jiǎn)單的AOP XML配置 對(duì)@AspectJ 切面的支持 對(duì)bean命名pointcut( bean name pointcut element)的支持 對(duì)AspectJ裝載時(shí)織入(AspectJ load-time weaving)的支持 中間層 在XML里更為簡(jiǎn)單的聲明性事務(wù)配置 對(duì)Websphere 事務(wù)管理的完整支持 JPA 異步的JMS JDBC Web層 Spring MVC合理的默認(rèn)值 Portlet 框架 基于Annotation的控制器 Spring MVC的表單標(biāo)簽庫(kù) 對(duì)Tiles 2 支持 對(duì)JSF 1.2支持 JAX-WS支持 其他 動(dòng)態(tài)語(yǔ)言支持 增強(qiáng)的測(cè)試支持 JMX 支持 將Spring 應(yīng)用程序上下文部署為JCA adapter 計(jì)劃任務(wù) 對(duì)Java 5 (Tiger) 支持 移植到Spring 2.5 改變 支持的JDK版本 Spring 2.5的Jar打包 XML配置 Deprecated(淘汰)的類(lèi)和方法 Apache OJB iBATIS Hibernate JDO UrlFilenameViewController 更新的樣例應(yīng)用 改進(jìn)的文檔 核心技術(shù) IoC(控制反轉(zhuǎn))容器 簡(jiǎn)介 基本原理 - 容器和bean 容器 配置元數(shù)據(jù) 實(shí)例化容器 XML配置元數(shù)據(jù)的結(jié)構(gòu) 多種bean bean的命名 bean的別名 實(shí)例化bean 用構(gòu)造器來(lái)實(shí)例化 使用靜態(tài)工廠方法實(shí)例化 使用實(shí)例工廠方法實(shí)例化 使用容器 依賴(lài) 注入依賴(lài) 構(gòu)造器注入 構(gòu)造器參數(shù)解析 構(gòu)造器參數(shù)類(lèi)型匹配 構(gòu)造參數(shù)索引 Setter注入 一些例子 依賴(lài)配置詳解 直接變量(基本類(lèi)型、Strings類(lèi)型等。) idref元素 引用其它的bean(協(xié)作者) 內(nèi)部bean 集合 集合的合并 強(qiáng)類(lèi)型集合(僅適用于Java5+) Nulls XML配置文件的簡(jiǎn)寫(xiě)及其他 XML-based configuration metadata shortcuts 使用p名稱(chēng)空間配置屬性 組合屬性名稱(chēng) 使用depends-on 延遲初始化bean 自動(dòng)裝配(autowire)協(xié)作者 將bean排除在自動(dòng)裝配之外 依賴(lài)檢查 方法注入 Lookup方法注入 自定義方法的替代方案 Bean的作用域 Singleton作用域 Prototype作用域 Singleton beans和prototype-bean的依賴(lài) 其他作用域 初始化web配置 Request作用域 Session作用域 global session作用域 作用域bean與依賴(lài) 選擇創(chuàng)建代理的類(lèi)型 自定義作用域 創(chuàng)建自定義作用域 使用自定義作用域 定制bean特性 生命周期回調(diào) 初始化回調(diào) 析構(gòu)回調(diào) 缺省的初始化和析構(gòu)方法 組合生命周期機(jī)制 在非web應(yīng)用中優(yōu)雅地關(guān)閉Spring IoC容器 了解自己 BeanFactoryAware BeanNameAware bean定義的繼承 容器擴(kuò)展點(diǎn) 用BeanPostProcessor定制bean 使用BeanPostProcessor的Hello World示例 RequiredAnnotationBeanPostProcessor示例 用BeanFactoryPostProcessor定制配置元數(shù)據(jù) PropertyPlaceholderConfigurer示例 PropertyOverrideConfigurer示例 使用FactoryBean定制實(shí)例化邏輯 The ApplicationContext BeanFactory 還是 ApplicationContext? 利用MessageSource實(shí)現(xiàn)國(guó)際化 事件 底層資源的訪問(wèn) ApplicationContext在WEB應(yīng)用中的實(shí)例化 粘合代碼和可怕的singleton 以J2EE RAR文件的形式部署Spring ApplicationContext 基于注解(Annotation-based)的配置 @Autowired 基于注解的自動(dòng)連接微調(diào) CustomAutowireConfigurer @Resource @PostConstruct 與 @PreDestroy 對(duì)受管組件的Classpath掃描 @Component和更多典型化注解 自動(dòng)檢測(cè)組件 使用過(guò)濾器自定義掃描 自動(dòng)檢測(cè)組件的命名 為自動(dòng)檢測(cè)的組件提供一個(gè)作用域 用注解提供限定符元數(shù)據(jù) 注冊(cè)一個(gè)LoadTimeWeaver 資源 簡(jiǎn)介 Resource接口 內(nèi)置 Resource 實(shí)現(xiàn) UrlResource ClassPathResource FileSystemResource ServletContextResource InputStreamResource ByteArrayResource ResourceLoader接口 ResourceLoaderAware 接口 把Resource作為屬性來(lái)配置 Application context 和Resource 路徑 構(gòu)造application context 創(chuàng)建 ClassPathXmlApplicationContext 實(shí)例 - 簡(jiǎn)介 Application context構(gòu)造器中資源路徑的通配符 Ant風(fēng)格的pattern 潛在的可移植性 classpath*: 前綴 其他關(guān)于通配符的說(shuō)明 FileSystemResource 說(shuō)明 校驗(yàn),數(shù)據(jù)綁定,BeanWrapper,與屬性編輯器 簡(jiǎn)介 使用Spring的Validator接口進(jìn)行校驗(yàn) 從錯(cuò)誤代碼到錯(cuò)誤信息 Bean處理和BeanWrapper 設(shè)置和獲取屬性值以及嵌套屬性 內(nèi)建的PropertyEditor實(shí)現(xiàn) 注冊(cè)用戶(hù)自定義的PropertyEditor 使用PropertyEditorRegistrars 使用Spring進(jìn)行面向切面編程(AOP) 簡(jiǎn)介 AOP概念 Spring AOP的功能和目標(biāo) AOP代理 @AspectJ支持 啟用@AspectJ支持 聲明一個(gè)切面 聲明一個(gè)切入點(diǎn)(pointcut) 切入點(diǎn)指示符(PCD)的支持 組合切入點(diǎn)表達(dá)式 共享通用切入點(diǎn)定義 示例 聲明通知 前置通知 后置通知(After returning advice) 異常通知(After throwing advice) 最終通知(After (finally) advice) 環(huán)繞通知 通知參數(shù)(Advice parameters) 訪問(wèn)當(dāng)前的連接點(diǎn) 傳遞參數(shù)給通知 確定參數(shù)名 處理參數(shù) 通知順序 引入(Introduction) 切面實(shí)例化模型 例子 基于Schema的AOP支持 聲明一個(gè)切面 聲明一個(gè)切入點(diǎn) 聲明通知 前置通知 后置通知 異常通知 最終通知 環(huán)繞通知 通知參數(shù) 通知順序 引入 切面實(shí)例化模型 Advisor 例子 AOP聲明風(fēng)格的選擇 Spring AOP還是完全用AspectJ? Spring AOP中使用@AspectJ還是XML? 混合切面類(lèi)型 代理機(jī)制 理解AOP代理 以編程方式創(chuàng)建@AspectJ代理 在Spring應(yīng)用中使用AspectJ 在Spring中使用AspectJ進(jìn)行domain object的依賴(lài)注入 @Configurable對(duì)象的單元測(cè)試 Working with multiple application contexts Spring中其他的AspectJ切面 使用Spring IoC來(lái)配置AspectJ的切面 在Spring應(yīng)用中使用AspectJ加載時(shí)織入(LTW) 第一個(gè)例子 切面 'META-INF/aop.xml' 相關(guān)類(lèi)庫(kù)(JARS) Spring配置 特定環(huán)境的配置 通用Java應(yīng)用 Tomcat WebLogic 更多資源 Spring AOP APIs 簡(jiǎn)介 Spring中的切入點(diǎn)API 概念 切入點(diǎn)運(yùn)算 AspectJ切入點(diǎn)表達(dá)式 便利的切入點(diǎn)實(shí)現(xiàn) 靜態(tài)切入點(diǎn) 正則表達(dá)式切入點(diǎn) 屬性驅(qū)動(dòng)的切入點(diǎn) 動(dòng)態(tài)切入點(diǎn) 控制流切入點(diǎn) 切入點(diǎn)的超類(lèi) 自定義切入點(diǎn) Spring的通知API 通知的生命周期 Spring里的通知類(lèi)型 攔截環(huán)繞通知 前置通知 異常通知 后置通知 引入通知 Spring里的Advisor API 使用ProxyFactoryBean創(chuàng)建AOP代理 基礎(chǔ) JavaBean屬性 基于JDK和CGLIB的代理 對(duì)接口進(jìn)行代理 對(duì)類(lèi)進(jìn)行代理 使用“全局”通知器 簡(jiǎn)化代理定義 使用ProxyFactory通過(guò)編程創(chuàng)建AOP代理 操作被通知對(duì)象 使用“自動(dòng)代理(autoproxy)”功能 自動(dòng)代理bean定義 BeanNameAutoProxyCreator DefaultAdvisorAutoProxyCreator AbstractAdvisorAutoProxyCreator 使用元數(shù)據(jù)驅(qū)動(dòng)的自動(dòng)代理 使用TargetSource 熱交換目標(biāo)源 池化目標(biāo)源 原型目標(biāo)源 ThreadLocal目標(biāo)源 定義新的Advice類(lèi)型 更多資源 測(cè)試 簡(jiǎn)介 單元測(cè)試 Mock對(duì)象 JNDI Servlet API Portlet API 單元測(cè)試支持類(lèi) 通用工具類(lèi) Spring MVC 集成測(cè)試 概覽 使用哪個(gè)支持框架 通用目標(biāo) 上下文管理及緩存 測(cè)試fixtures依賴(lài)注入 事務(wù)管理 集成測(cè)試支持類(lèi) JDBC測(cè)試支持 常用注解 JUnit 3.8遺留支持 上下文管理及緩存 測(cè)試fixture依賴(lài)注入 字段級(jí)別(Field Level)注入 事務(wù)管理 JUnit 3.8 遺留支持類(lèi) Java 5+ 專(zhuān)有支持 使用注解的事務(wù)相關(guān)測(cè)試 JPA支持類(lèi) Spring TestContext Framework 主要的抽象 上下文管理和緩存 測(cè)試fixture的依賴(lài)注入 事務(wù)管理 TestContext支持類(lèi) JUnit 3.8支持類(lèi) JUnit 4.4支持類(lèi) 定制JUnit 4.4運(yùn)行器 TestNG支持類(lèi) TestContext框架注解支持 PetClinic示例 更多資源 中間層數(shù)據(jù)訪問(wèn) 事務(wù)管理 簡(jiǎn)介 動(dòng)機(jī) 關(guān)鍵抽象 使用資源同步的事務(wù) 高層次方案 低層次方案 TransactionAwareDataSourceProxy 聲明式事務(wù)管理 理解Spring的聲明式事務(wù)管理實(shí)現(xiàn) 第一個(gè)例子 回滾 為不同的bean配置不同的事務(wù)語(yǔ)義 <tx:advice/> 有關(guān)的設(shè)置 使用 @Transactional @Transactional 有關(guān)的設(shè)置 事務(wù)傳播 required RequiresNew Nested 通知事務(wù)操作 結(jié)合AspectJ使用 @Transactional 編程式事務(wù)管理 使用TransactionTemplate 指定事務(wù)設(shè)置 使用PlatformTransactionManager 選擇編程式事務(wù)管理還是聲明式事務(wù)管理 與特定應(yīng)用服務(wù)器集成 IBM WebSphere BEA WebLogic Oracle OC4J 常見(jiàn)問(wèn)題的解決方法 對(duì)一個(gè)特定的 DataSource 使用了錯(cuò)誤的事務(wù)管理器 更多的資源 DAO支持 簡(jiǎn)介 一致的異常層次 一致的DAO支持抽象類(lèi) 使用JDBC進(jìn)行數(shù)據(jù)訪問(wèn) 簡(jiǎn)介 選擇一種工作模式 Spring JDBC包結(jié)構(gòu) 利用JDBC核心類(lèi)控制JDBC的基本操作和錯(cuò)誤處理 JdbcTemplate類(lèi) 一些示例 查詢(xún)(SELECT) 更新(INSERT/UPDATE/DELETE) 其他操作 JdbcTemplate 的最佳實(shí)踐 NamedParameterJdbcTemplate類(lèi) SimpleJdbcTemplate類(lèi) DataSource接口 SQLExceptionTranslator接口 執(zhí)行SQL語(yǔ)句 執(zhí)行查詢(xún) 更新數(shù)據(jù)庫(kù) 獲取自動(dòng)生成的主鍵 控制數(shù)據(jù)庫(kù)連接 DataSourceUtils類(lèi) SmartDataSource接口 AbstractDataSource類(lèi) SingleConnectionDataSource類(lèi) DriverManagerDataSource類(lèi) TransactionAwareDataSourceProxy類(lèi) DataSourceTransactionManager類(lèi) NativeJdbcExtractor JDBC批量操作 使用JdbcTemplate進(jìn)行批量操作 使用SimpleJdbcTemplate進(jìn)行批量操作 通過(guò)使用SimpleJdbc類(lèi)簡(jiǎn)化JDBC操作 使用SimpleJdbcInsert插入數(shù)據(jù) 使用SimpleJdbcInsert來(lái)獲取自動(dòng)生成的主鍵 指定SimpleJdbcInsert所使用的字段 使用SqlParameterSource提供參數(shù)值 使用SimpleJdbcCall調(diào)用存儲(chǔ)過(guò)程 聲明SimpleJdbcCall使用的參數(shù) 如何定義SqlParameters 使用SimpleJdbcCall調(diào)用內(nèi)置函數(shù) 使用SimpleJdbcCall返回的ResultSet/REF Cursor 用Java對(duì)象來(lái)表達(dá)JDBC操作 SqlQuery類(lèi) MappingSqlQuery類(lèi) SqlUpdate類(lèi) StoredProcedure類(lèi) SqlFunction類(lèi) 參數(shù)和數(shù)據(jù)處理的基本原則 為參數(shù)設(shè)置SQL類(lèi)型信息 處理BLOB 和 CLOB對(duì)象 在IN語(yǔ)句中傳入一組參數(shù)值 處理復(fù)雜類(lèi)型的存儲(chǔ)過(guò)程調(diào)用 使用ORM工具進(jìn)行數(shù)據(jù)訪問(wèn) 簡(jiǎn)介 Hibernate 資源管理 在Spring容器中創(chuàng)建 SessionFactory The HibernateTemplate 不使用回調(diào)的基于Spring的DAO實(shí)現(xiàn) 基于Hibernate3的原生API實(shí)現(xiàn)DAO 編程式的事務(wù)劃分 聲明式的事務(wù)劃分 事務(wù)管理策略 容器資源 vs 本地資源 在應(yīng)用服務(wù)器中使用Hibernate的注意事項(xiàng) JDO 建立PersistenceManagerFactory JdoTemplate和JdoDaoSupport 基于原生的JDO API實(shí)現(xiàn)DAO 事務(wù)管理 JdoDialect Oracle TopLink SessionFactory 抽象層 TopLinkTemplate and TopLinkDaoSupport 基于原生的TopLink API的DAO實(shí)現(xiàn) 事務(wù)管理 iBATIS SQL Maps 創(chuàng)建SqlMapClient 使用 SqlMapClientTemplate 和 SqlMapClientDaoSupport 基于原生的iBATIS API的DAO實(shí)現(xiàn) JPA 在Spring環(huán)境中建立JPA LocalEntityManagerFactoryBean 從JNDI中獲取 EntityManagerFactory LocalContainerEntityManagerFactoryBean Tomcat(5.0以上)加載時(shí)的織入配置 使用VM代理的全局加載時(shí)織入 上下文范圍內(nèi)的加載時(shí)織入配置 處理多持久化單元 JpaTemplate 和 JpaDaoSupport 基于原生的JPA實(shí)現(xiàn)DAO 異常轉(zhuǎn)化 事務(wù)管理 JpaDialect The Web Web MVC framework Web框架 概述 與其他MVC實(shí)現(xiàn)框架的集成 Spring Web MVC框架的特點(diǎn) DispatcherServlet 控制器 AbstractController 和 WebContentGenerator 其它的簡(jiǎn)單控制器 MultiActionController 命令控制器 處理器映射(handler mapping) BeanNameUrlHandlerMapping SimpleUrlHandlerMapping 攔截器(HandlerInterceptor) 視圖與視圖解析 視圖解析器(ViewResolver) 視圖解析鏈 重定向(Rediret)到另一個(gè)視圖 RedirectView redirect:前綴 forward:前綴 本地化解析器 AcceptHeaderLocaleResolver CookieLocaleResolver SessionLocaleResolver LocaleChangeInterceptor 使用主題 簡(jiǎn)介 如何定義主題 主題解析器 Spring對(duì)分段文件上傳(multipart file upload)的支持 介紹 使用MultipartResolver 在表單中處理分段文件上傳 使用Spring的表單標(biāo)簽庫(kù) 配置 form標(biāo)簽 input標(biāo)簽 checkbox標(biāo)簽 checkboxes標(biāo)簽 radiobutton標(biāo)簽 radiobuttons標(biāo)簽 password標(biāo)簽 select標(biāo)簽 option標(biāo)簽 options標(biāo)簽 textarea標(biāo)簽 hidden標(biāo)簽 errors標(biāo)簽 處理異常 慣例優(yōu)先原則(convention over configuration) 對(duì)控制器的支持:ControllerClassNameHandlerMapping 對(duì)模型的支持:ModelMap(ModelAndView) 對(duì)視圖的支持:RequestToViewNameTranslator 基于注解的控制器配置 建立dispatcher實(shí)現(xiàn)注解支持 使用@Controller定義一個(gè)控制器 使用@RequestMapping映射請(qǐng)求 使用@RequestParam綁定請(qǐng)求參數(shù)到方法參數(shù) 使用@ModelAttribute提供一個(gè)從模型到數(shù)據(jù)的鏈接 使用@SessionAttributes指定存儲(chǔ)在會(huì)話(huà)中的屬性 自定義WebDataBinder初始化 使用@InitBinder自定義數(shù)據(jù)綁定 配置一個(gè)定制的WebBindingInitializer 更多資源 集成視圖技術(shù) 簡(jiǎn)介 JSP和JSTL 視圖解析器 'Plain-old' JSPs versus JSTL 'Plain-old' JSP與JSTL 幫助簡(jiǎn)化開(kāi)發(fā)的額外的標(biāo)簽 Tiles 需要的資源 如何集成Tiles UrlBasedViewResolver類(lèi) ResourceBundleViewResolver類(lèi) SimpleSpringPreparerFactory 和 SpringBeanPreparerFactory Velocity和FreeMarker 需要的資源 Context 配置 創(chuàng)建模板 高級(jí)配置 velocity.properties FreeMarker 綁定支持和表單處理 用于綁定的宏 簡(jiǎn)單綁定 表單輸入生成宏 輸入域 選擇輸入域 重載HTML轉(zhuǎn)碼行為并使你的標(biāo)簽符合XHTML XSLT 寫(xiě)在段首 Bean 定義 標(biāo)準(zhǔn)MVC控制器代碼 把模型數(shù)據(jù)轉(zhuǎn)化為XML 定義視圖屬性 文檔轉(zhuǎn)換 小結(jié) 文檔視圖(PDF/Excel) 簡(jiǎn)介 配置和安裝 文檔視圖定義 Controller 代碼 Excel視圖子類(lèi) PDF視圖子類(lèi) JasperReports 依賴(lài)的資源 配置 配置ViewResolver 配置View 關(guān)于報(bào)表文件 使用 JasperReportsMultiFormatView 構(gòu)造ModelAndView 使用子報(bào)表 配置子報(bào)表文件 配置子報(bào)表數(shù)據(jù)源 配置Exporter的參數(shù) 集成其它Web框架 簡(jiǎn)介 通用配置 JavaServer Faces DelegatingVariableResolver FacesContextUtils Struts ContextLoaderPlugin DelegatingRequestProcessor DelegatingActionProxy ActionSupport Classes Tapestry 注入 Spring 托管的 beans 將 Spring Beans 注入到 Tapestry 頁(yè)面中 組件定義文件 添加抽象訪問(wèn)方法 將 Spring Beans 注入到 Tapestry 頁(yè)面中 - Tapestry 4.0+ 風(fēng)格 WebWork 更多資源 Portlet MVC框架 介紹 控制器 - MVC中的C 視圖 - MVC中的V Web作用范圍的Bean DispatcherPortlet ViewRendererServlet 控制器 AbstractController 和 PortletContentGenerator 其它簡(jiǎn)單的控制器 Command控制器 PortletWrappingController 處理器映射 PortletModeHandlerMapping ParameterHandlerMapping PortletModeParameterHandlerMapping 增加 HandlerInterceptors HandlerInterceptorAdapter ParameterMappingInterceptor 視圖和它們的解析 Multipart文件上傳支持 使用 PortletMultipartResolver 處理表單里的文件上傳 異常處理 Portlet應(yīng)用的部署 整合 使用Spring進(jìn)行遠(yuǎn)程訪問(wèn)與Web服務(wù) 簡(jiǎn)介 使用RMI暴露服務(wù) 使用RmiServiceExporter暴露服務(wù) 在客戶(hù)端鏈接服務(wù) 使用Hessian或者Burlap通過(guò)HTTP遠(yuǎn)程調(diào)用服務(wù) 為Hessian和co.配置DispatcherServlet 使用HessianServiceExporter暴露你的bean 在客戶(hù)端連接服務(wù) 使用Burlap 對(duì)通過(guò)Hessian或Burlap暴露的服務(wù)使用HTTP Basic認(rèn)證 使用HTTP調(diào)用器暴露服務(wù) Exposing the service object 在客戶(hù)端連接服務(wù) Web Services 使用JAX-RPC暴露基于servlet的web服務(wù) 使用JAX-RPC訪問(wèn)web服務(wù) 注冊(cè)JAX-RPC Bean映射 注冊(cè)自己的JAX-RPC 處理器 使用JAX-WS暴露基于servlet的web服務(wù) 使用JAX-WS暴露單獨(dú)web服務(wù) 使用Spring支持的JAX-WS RI來(lái)暴露服務(wù) 使用JAX-WS訪問(wèn)web服務(wù) 使用XFire來(lái)暴露Web服務(wù) JMS 服務(wù)端配置 客戶(hù)端配置 對(duì)遠(yuǎn)程接口不提供自動(dòng)探測(cè)實(shí)現(xiàn) 在選擇這些技術(shù)時(shí)的一些考慮 Enterprise Java Beans (EJB) 集成 簡(jiǎn)介 訪問(wèn)EJB 概念 訪問(wèn)本地的無(wú)狀態(tài)Session Bean(SLSB) 訪問(wèn)遠(yuǎn)程SLSB Accessing EJB 2.x SLSBs versus EJB 3 SLSBs 使用Spring提供的輔助類(lèi)實(shí)現(xiàn)EJB組件 EJB 2.x base classes EJB 3 注入攔截 JMS (Java Message Service) 簡(jiǎn)介 使用Spring JMS JmsTemplate 連接工廠 目的地管理 消息偵聽(tīng)容器 SimpleMessageListenerContainer DefaultMessageListenerContainer ServerSessionMessageListenerContainer 事務(wù)管理 發(fā)送消息 使用消息轉(zhuǎn)換器 SessionCallback 和 ProducerCallback 接收消息 同步接收 異步接收 - 消息驅(qū)動(dòng)的POJO SessionAwareMessageListener接口 MessageListenerAdapter 事務(wù)中的消息處理 JCA消息端點(diǎn)的支持 JMS命名空間支持 JMX 介紹 將Bean暴露為JMX 創(chuàng)建MBeanServer 重用原有的MBeanServer 延遲初始化的MBean MBean的自動(dòng)注冊(cè) 控制注冊(cè)行為 控制Bean的管理接口 MBeanInfoAssembler接口 使用源碼級(jí)元數(shù)據(jù) 使用JDK 5.0的注解 源代碼級(jí)的元數(shù)據(jù)類(lèi)型 AutodetectCapableMBeanInfoAssembler接口 用Java接口定義管理接口 使用MethodNameBasedMBeanInfoAssembler 控制Bean的ObjectName 從Properties讀取Properties 使用MetadataNamingStrategy <context:mbean-export/>元素 JSR-160連接器 服務(wù)器端連接器 客戶(hù)端連接器 基于Burlap/Hessian/SOAP的JMX 通過(guò)代理訪問(wèn)MBean 通知 為通知注冊(cè)監(jiān)聽(tīng)器 發(fā)布通知 更多資源 JCA CCI 簡(jiǎn)介 配置CCI 連接器配置 在Spring中配置ConnectionFactory 配置CCI連接 使用一個(gè) CCI 單連接 使用Spring的 CCI訪問(wèn)支持 記錄轉(zhuǎn)換 CciTemplate類(lèi) DAO支持 自動(dòng)輸出記錄生成 總結(jié) 直接使用一個(gè)CCI Connection接口和Interaction接口 CciTemplate 使用示例 建模CCI訪問(wèn)為操作對(duì)象 MappingRecordOperation MappingCommAreaOperation 自動(dòng)生成輸出記錄 總結(jié) MappingRecordOperation 使用示例 MappingCommAreaOperation 使用示例 事務(wù) Spring郵件抽象層 簡(jiǎn)介 使用Spring郵件抽象 MailSender 和 SimpleMailMessage 的基本用法 使用 JavaMailSender 和 MimeMessagePreparator 使用MimeMessageHelper 發(fā)送附件和嵌入式資源(inline resources) 附件 內(nèi)嵌資源 使用模板來(lái)創(chuàng)建郵件內(nèi)容 一個(gè)基于Velocity的示例 Spring中的定時(shí)調(diào)度(Scheduling)和線(xiàn)程池(Thread Pooling) 簡(jiǎn)介 使用OpenSymphony Quartz 調(diào)度器 使用JobDetailBean 使用 MethodInvokingJobDetailFactoryBean 使用triggers和SchedulerFactoryBean來(lái)包裝任務(wù) 使用JDK Timer支持類(lèi) 創(chuàng)建定制的timers 使用 MethodInvokingTimerTaskFactoryBean類(lèi) 最后:使用TimerFactoryBean來(lái)設(shè)置任務(wù) SpringTaskExecutor抽象 TaskExecutor接口 TaskExecutor類(lèi)型 使用TaskExecutor 動(dòng)態(tài)語(yǔ)言支持 介紹 第一個(gè)示例 定義動(dòng)態(tài)語(yǔ)言支持的bean 公共概念 <lang:language/> 元素 Refreshable bean 內(nèi)置動(dòng)態(tài)語(yǔ)言源文件 理解dynamic-language-backed bean上下文中的構(gòu)造器注入 JRuby beans Groovy beans 通過(guò)回調(diào)定制Groovy對(duì)象 BeanShell beans 場(chǎng)景 Spring MVC控制器的腳本化 Validator的腳本化 Bits and bobs AOP - 通知腳本化bean 作用域 更多的資源 注解和源代碼級(jí)的元數(shù)據(jù)支持 簡(jiǎn)介 Spring的元數(shù)據(jù)支持 注解 @Required Spring中的其它@Annotations Jakarta Commons Attributes集成 元數(shù)據(jù)和Spring AOP自動(dòng)代理 基本原理 聲明式事務(wù)管理 示例程序 演示案例 介紹 使用動(dòng)態(tài)語(yǔ)言實(shí)現(xiàn)的Spring MVC控制器 構(gòu)建與部署 使用SimpleJdbcTemplate和@Repository實(shí)現(xiàn)DAO 域?qū)ο?/a> Data Access Object 構(gòu)建 XML Schema-based configuration Introduction XML Schema-based configuration Referencing the schemas The util schema <util:constant/> Setting a bean property or constructor arg from a field value <util:property-path/> Using <util:property-path/> to set a bean property or constructor-argument <util:properties/> <util:list/> <util:map/> <util:set/> The jee schema <jee:jndi-lookup/> (simple) <jee:jndi-lookup/> (with single JNDI environment setting) <jee:jndi-lookup/> (with multiple JNDI environment settings) <jee:jndi-lookup/> (complex) <jee:local-slsb/> (simple) <jee:local-slsb/> (complex) <jee:remote-slsb/> The lang schema The jms schema The tx (transaction) schema The aop schema The context schema <property-placeholder/> <annotation-config/> <component-scan/> <load-time-weaver/> <spring-configured/> <mbean-export/> The tool schema The beans schema Setting up your IDE Setting up Eclipse Setting up IntelliJ IDEA Integration issues XML parsing errors in the Resin v.3 application server Extensible XML authoring Introduction Authoring the schema Coding a NamespaceHandler Coding a BeanDefinitionParser Registering the handler and the schema 'META-INF/spring.handlers' 'META-INF/spring.schemas' Using a custom extension in your Spring XML configuration Meatier examples Nesting custom tags within custom tags Custom attributes on 'normal' elements Further Resources spring-beans-2.0.dtd spring.tld Introduction The bind tag The escapeBody tag The hasBindErrors tag The htmlEscape tag The message tag The nestedPath tag The theme tag The transform tag spring-form.tld Introduction The checkbox tag The checkboxes tag The errors tag The form tag The hidden tag The input tag The label tag The option tag The options tag The password tag The radiobutton tag The radiobuttons tag The select tag The textarea tag Spring 2.5開(kāi)發(fā)手冊(cè)中文化項(xiàng)目 聲明 致謝 參與人員 項(xiàng)目歷程
文字

11.2.?利用JDBC核心類(lèi)控制JDBC的基本操作和錯(cuò)誤處理

11.2.1.?JdbcTemplate類(lèi)

JdbcTemplate是core包的核心類(lèi)。它替我們完成了資源的創(chuàng)建以及釋放工作,從而簡(jiǎn)化了我們對(duì)JDBC的使用。 它還可以幫助我們避免一些常見(jiàn)的錯(cuò)誤,比如忘記關(guān)閉數(shù)據(jù)庫(kù)連接。 JdbcTemplate將完成JDBC核心處理流程,比如SQL語(yǔ)句的創(chuàng)建、執(zhí)行,而把SQL語(yǔ)句的生成以及查詢(xún)結(jié)果的提取工作留給我們的應(yīng)用代碼。 它可以完成SQL查詢(xún)、更新以及調(diào)用存儲(chǔ)過(guò)程,可以對(duì)ResultSet進(jìn)行遍歷并加以提取。 它還可以捕獲JDBC異常并將其轉(zhuǎn)換成org.springframework.dao包中定義的,通用的,信息更豐富的異常。

使用JdbcTemplate進(jìn)行編碼只需要根據(jù)明確定義的一組契約來(lái)實(shí)現(xiàn)回調(diào)接口。 PreparedStatementCreator回調(diào)接口通過(guò)給定的Connection創(chuàng)建一個(gè)PreparedStatement,包含SQL和任何相關(guān)的參數(shù)。 CallableStatementCreateor實(shí)現(xiàn)同樣的處理,只不過(guò)它創(chuàng)建的是CallableStatement。 RowCallbackHandler接口則從數(shù)據(jù)集的每一行中提取值。

我們可以在DAO實(shí)現(xiàn)類(lèi)中通過(guò)傳遞一個(gè)DataSource引用來(lái)完成JdbcTemplate的實(shí)例化,也可以在Spring的IoC容器中配置一個(gè)JdbcTemplate的bean并賦予DAO實(shí)現(xiàn)類(lèi)作為一個(gè)實(shí)例。 需要注意的是DataSource在Spring的IoC容器中總是配制成一個(gè)bean,第一種情況下,DataSource bean將傳遞給service,第二種情況下DataSource bean傳遞給JdbcTemplate bean。

最后,JdbcTemplate中使用的所有SQL將會(huì)以“DEBUG”級(jí)別記入日志(一般情況下日志的category是JdbcTemplate相應(yīng)的全限定類(lèi)名,不過(guò)如果需要對(duì)JdbcTemplate進(jìn)行定制的話(huà),可能是它的子類(lèi)名)。

11.2.1.1.?一些示例

下面是一些使用JdbcTemplate類(lèi)的示例。(這些示例并不是完整展示所有的JdbcTemplate所暴露出來(lái)的功能。請(qǐng)查看與之相關(guān)的Javadoc)。

11.2.1.1.1.?查詢(xún)(SELECT)

一個(gè)簡(jiǎn)單的例子用于展示如何獲取一個(gè)表中的所有行數(shù)。

int rowCount = this.jdbcTemplate.queryForInt("select count(0) from t_accrual");

一個(gè)簡(jiǎn)單的例子展示如何進(jìn)行參數(shù)綁定。

int countOfActorsNamedJoe = this.jdbcTemplate.queryForInt(
        "select count(0) from t_actors where first_name = ?", new Object[]{"Joe"});

查詢(xún)一個(gè)String

String surname = (String) this.jdbcTemplate.queryForObject(
        "select surname from t_actor where id = ?", 
        new Object[]{new Long(1212)}, String.class);

查詢(xún)并將結(jié)果記錄為一個(gè)簡(jiǎn)單的數(shù)據(jù)模型。

Actor actor = (Actor) this.jdbcTemplate.queryForObject(
    "select first_name, surname from t_actor where id = ?",
    new Object[]{new Long(1212)},
    new RowMapper() {

        public Object mapRow(ResultSet rs, int rowNum) throws SQLException {
            Actor actor = new Actor();
            actor.setFirstName(rs.getString("first_name"));
            actor.setSurname(rs.getString("surname"));
            return actor;
        }
    });

查詢(xún)并組裝多個(gè)數(shù)據(jù)模型。

Collection actors = this.jdbcTemplate.query(
    "select first_name, surname from t_actor",
    new RowMapper() {

        public Object mapRow(ResultSet rs, int rowNum) throws SQLException {
            Actor actor = new Actor();
            actor.setFirstName(rs.getString("first_name"));
            actor.setSurname(rs.getString("surname"));
            return actor;
        }
    });

如果最后2個(gè)示例中的代碼出現(xiàn)在同一段程序中,我們有必要去掉這些重復(fù)的RowMapper匿名類(lèi)代碼,將這些代碼抽取到一個(gè)單獨(dú)的類(lèi)中(通常是一個(gè)靜態(tài)的內(nèi)部類(lèi))。 這樣,這個(gè)內(nèi)部類(lèi)就可以在DAO的方法中被共享。因而,最后2個(gè)示例寫(xiě)成如下的形式將更加好:

public Collection findAllActors() {
    return this.jdbcTemplate.query( "select first_name, surname from t_actor", new ActorMapper());
}

private static final class ActorMapper implements RowMapper {

    public Object mapRow(ResultSet rs, int rowNum) throws SQLException {
        Actor actor = new Actor();
        actor.setFirstName(rs.getString("first_name"));
        actor.setSurname(rs.getString("surname"));
        return actor;
    }
}
11.2.1.1.2.?更新(INSERT/UPDATE/DELETE)
this.jdbcTemplate.update(
        "insert into t_actor (first_name, surname) values (?, ?)", 
        new Object[] {"Leonor", "Watling"});
this.jdbcTemplate.update(
        "update t_actor set weapon = ? where id = ?", 
        new Object[] {"Banjo", new Long(5276)});
this.jdbcTemplate.update(
        "delete from actor where id = ?",
        new Object[] {new Long.valueOf(actorId)});
11.2.1.1.3.?其他操作

execute(..)方法可以被用作執(zhí)行任何類(lèi)型的SQL,甚至是DDL語(yǔ)句。 這個(gè)方法的實(shí)現(xiàn)需要傳入一個(gè)回調(diào)接口、需要綁定的參數(shù)數(shù)組等作為參數(shù)。

this.jdbcTemplate.execute("create table mytable (id integer, name varchar(100))");

調(diào)用一個(gè)簡(jiǎn)單的存儲(chǔ)過(guò)程(更多復(fù)雜的存儲(chǔ)過(guò)程支持請(qǐng)參見(jiàn)存儲(chǔ)過(guò)程支持)。

this.jdbcTemplate.update(
        "call SUPPORT.REFRESH_ACTORS_SUMMARY(?)", 
        new Object[]{Long.valueOf(unionId)});

11.2.1.2.?JdbcTemplate 的最佳實(shí)踐

JdbcTemplate類(lèi)的實(shí)例是線(xiàn)程安全的實(shí)例。這一點(diǎn)非常重要,正因?yàn)槿绱?,你可以配置一個(gè)簡(jiǎn)單的JdbcTemplate實(shí)例,并將這個(gè)“共享的”、“安全的”實(shí)例注入到不同的DAO類(lèi)中去。 另外, JdbcTemplate 是有狀態(tài)的,因?yàn)樗S護(hù)的DataSource 實(shí)例是有狀態(tài)的,但是這種狀態(tài)是無(wú)法變化的。

使用JdbcTemplate的一個(gè)常見(jiàn)的最佳實(shí)踐(同時(shí)也是SimpleJdbcTemplateNamedParameterJdbcTemplate 類(lèi)的最佳實(shí)踐)就是在Spring配置文件中配置一個(gè)DataSource實(shí)例,然后將這個(gè)共享的DataSource實(shí)例助于到你的DAO中去。 而JdbcTemplate的實(shí)例將在DataSource的setter方法中被創(chuàng)建。這樣的話(huà),DAO可能看上去像這樣:

public class JdbcCorporateEventDao implements CorporateEventDao {

    private JdbcTemplate jdbcTemplate;

    public void setDataSource(DataSource dataSource) {
        this.jdbcTemplate = new JdbcTemplate(dataSource);
    }

    // JDBC-backed implementations of the methods on the CorporateEventDao follow...
}

相關(guān)的配置看上去就像這樣。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans 
       http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">

    <bean id="corporateEventDao" class="com.example.JdbcCorporateEventDao">
        <property name="dataSource" ref="dataSource"/>
    </bean>

    <!-- the DataSource (parameterized for configuration via a PropertyPlaceHolderConfigurer) -->
    <bean id="dataSource" destroy-method="close" class="org.apache.commons.dbcp.BasicDataSource">
        <property name="driverClassName" value="${jdbc.driverClassName}"/>
        <property name="url" value="${jdbc.url}"/>
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
    </bean>

</beans>

如果你使用Spring提供的JdbcDaoSupport類(lèi),并且你的那些基于JDBC的DAO都繼承自這個(gè)類(lèi),那么你會(huì)自動(dòng)地從JdbcDaoSupport類(lèi)中繼承了setDataSource(..)方法。 是否將你的DAO類(lèi)繼承自這些類(lèi)完全取決于你自己的決定,事實(shí)上這并不是必須的,如果你看一下JdbcDaoSupport類(lèi)你會(huì)發(fā)現(xiàn),這里只是提供了一個(gè)簡(jiǎn)便的方式而已。

無(wú)論你是否使用上述這種初始化方式,都無(wú)需在執(zhí)行某些SQL操作時(shí)多次創(chuàng)建一個(gè)JdbcTemplate實(shí)例。記住,一旦JdbcTemplate被創(chuàng)建,他是一個(gè)線(xiàn)程安全的對(duì)象。 一個(gè)你需要?jiǎng)?chuàng)建多次JdbcTemplate實(shí)例的理由可能在于,你的應(yīng)用需要訪問(wèn)多個(gè)不同的數(shù)據(jù)庫(kù),從而需要不同的DataSources來(lái)創(chuàng)建不同的JdbcTemplates實(shí)例。

11.2.2.?NamedParameterJdbcTemplate類(lèi)

NamedParameterJdbcTemplate類(lèi)為JDBC操作增加了命名參數(shù)的特性支持,而不是傳統(tǒng)的使用('?')作為參數(shù)的占位符。NamedParameterJdbcTemplate類(lèi)對(duì)JdbcTemplate類(lèi)進(jìn)行了封裝, 在底層,JdbcTemplate完成了多數(shù)的工作。這一個(gè)章節(jié)將主要描述NamedParameterJdbcTemplate類(lèi)與JdbcTemplate類(lèi)的一些區(qū)別,也就是使用命名參數(shù)進(jìn)行JDBC操作。

// some JDBC-backed DAO class...
private NamedParameterJdbcTemplate namedParameterJdbcTemplate;

public void setDataSource(DataSource dataSource) {
    this.namedParameterJdbcTemplate = new NamedParameterJdbcTemplate(dataSource);
}

public int countOfActorsByFirstName(String firstName) {

    String sql = "select count(0) from T_ACTOR where first_name = :first_name";

    SqlParameterSource namedParameters = new MapSqlParameterSource("first_name", firstName);

    return namedParameterJdbcTemplate.queryForInt(sql, namedParameters);
}

注意這里在'sql'中使用了命名參數(shù)作為變量,而這個(gè)名稱(chēng)所對(duì)應(yīng)的值被定義在傳入的'namedParameters' 中作為參數(shù)(也可以傳入到MapSqlParameterSource中作為參數(shù))。

你也可以傳入許多命名參數(shù)以及他們所對(duì)應(yīng)的值,以Map的方式,作為鍵值對(duì)傳入到NamedParameterJdbcTemplate中。 (其余的被NamedParameterJdbcOperations所暴露的接口以及NamedParameterJdbcTemplate實(shí)現(xiàn)類(lèi)遵循了類(lèi)似的方式,此處不包含相關(guān)內(nèi)容)。

// some JDBC-backed DAO class...
private NamedParameterJdbcTemplate namedParameterJdbcTemplate;

public void setDataSource(DataSource dataSource) {
    this.namedParameterJdbcTemplate = new NamedParameterJdbcTemplate(dataSource);
}

public int countOfActorsByFirstName(String firstName) {

    String sql = "select count(0) from T_ACTOR where first_name = :first_name";

    Map namedParameters = Collections.singletonMap("first_name", firstName);

    return this.namedParameterJdbcTemplate.queryForInt(sql, namedParameters);
}

NamedParameterJdbcTemplate類(lèi)所具備的另外一個(gè)比較好的特性就是可以接收SqlParameterSource作為傳入?yún)?shù) (這個(gè)類(lèi)位于相同的包定義中)。 你已經(jīng)在先前的一個(gè)例子中看到了這個(gè)接口的一個(gè)具體實(shí)現(xiàn)類(lèi)。( MapSqlParameterSource類(lèi))。而SqlParameterSource 這個(gè)接口對(duì)于NamedParameterJdbcTemplate類(lèi)的操作而言是一個(gè)傳入的參數(shù)。MapSqlParameterSource只是一個(gè)非常簡(jiǎn)單的實(shí)現(xiàn),使用了java.util.Map作為轉(zhuǎn)接器, 其中,Map中的Key表示參數(shù)名稱(chēng),而Map中的Value表示參數(shù)值。

另外一個(gè)SqlParameterSource 的實(shí)現(xiàn)類(lèi)是BeanPropertySqlParameterSource。這個(gè)類(lèi)對(duì)傳統(tǒng)的Java進(jìn)行了封裝(也就是那些符合JavaBean標(biāo)準(zhǔn)的類(lèi)), 并且使用了JavaBean的屬性作為參數(shù)的名稱(chēng)和值。

public class Actor {

    private Long id;
    private String firstName;
    private String lastName;
    
    public String getFirstName() {
        return this.firstName;
    }
    
    public String getLastName() {
        return this.lastName;
    }
    
    public Long getId() {
        return this.id;
    }
    
    // setters omitted...

}
// some JDBC-backed DAO class...
private NamedParameterJdbcTemplate namedParameterJdbcTemplate;

public void setDataSource(DataSource dataSource) {
    this.namedParameterJdbcTemplate = new NamedParameterJdbcTemplate(dataSource);
}

public int countOfActors(Actor exampleActor) {

    // notice how the named parameters match the properties of the above 'Actor' class
    String sql = "select count(0) from T_ACTOR where first_name = :firstName and last_name = :lastName";

    SqlParameterSource namedParameters = new BeanPropertySqlParameterSource(exampleActor);

    return this.namedParameterJdbcTemplate.queryForInt(sql, namedParameters);
}

注意,NamedParameterJdbcTemplate類(lèi)只是封裝JdbcTemplate模板; 因而如果你需要訪問(wèn)相應(yīng)被封裝的JdbcTemplate類(lèi),并訪問(wèn)一些只有在JdbcTemplate中擁有的功能,你需要使用getJdbcOperations()方法來(lái)進(jìn)行訪問(wèn)。

請(qǐng)參照第?11.2.1.2?節(jié) “JdbcTemplate 的最佳實(shí)踐”來(lái)獲取一些使用NamedParameterJdbcTemplate的最佳實(shí)踐。

11.2.3.?SimpleJdbcTemplate類(lèi)

注意

SimpleJdbcTemplate所提供的一些特性必須工作在Java 5及以上版本。

SimpleJdbcTemplate類(lèi)是對(duì)JdbcTemplate類(lèi)進(jìn)行的封裝,從而可以充分利用Java 5所帶來(lái)的varargs和autoboxing等特性。 SimpleJdbcTemplate類(lèi)完全利用了Java 5語(yǔ)法所帶來(lái)的蜜糖效應(yīng)。凡是使用過(guò)Java 5的程序員們?nèi)绻獜腏ava 5遷移回之前的JDK版本,無(wú)疑會(huì)發(fā)現(xiàn)這些特性所帶來(lái)的蜜糖效應(yīng)。

“before and after”示例可以成為SimpleJdbcTemplate類(lèi)所帶來(lái)的蜜糖效應(yīng)的最佳詮釋。 下面的代碼示例首先展示了使用傳統(tǒng)的JdbcTemplate進(jìn)行JDBC訪問(wèn)的代碼,接著是使用SimpleJdbcTemplate類(lèi)做同樣的事情。

// classic JdbcTemplate-style...
private JdbcTemplate jdbcTemplate;

public void setDataSource(DataSource dataSource) {
    this.jdbcTemplate = new JdbcTemplate(dataSource);
}

public Actor findActor(long id) {
    String sql = "select id, first_name, last_name from T_ACTOR where id = ?";
    
    RowMapper mapper = new RowMapper() {
    
        public Object mapRow(ResultSet rs, int rowNum) throws SQLException {
            Actor actor = new Actor();
            actor.setId(rs.getLong("id"));
            actor.setFirstName(rs.getString("first_name"));
            actor.setLastName(rs.getString("last_name"));
            return actor;
        }
    };
    
    // notice the cast, the wrapping up of the 'id' argument
    // in an array, and the boxing of the 'id' argument as a reference type
    return (Actor) jdbcTemplate.queryForObject(sql, mapper, new Object[] {Long.valueOf(id)});
}

下面是同樣的邏輯,使用了SimpleJdbcTemplate;可以看到代碼“干凈”多了:

// SimpleJdbcTemplate-style...
private SimpleJdbcTemplate simpleJdbcTemplate;

public void setDataSource(DataSource dataSource) {
    this.simpleJdbcTemplate = new SimpleJdbcTemplate(dataSource);
}

public Actor findActor(long id) {
    String sql = "select id, first_name, last_name from T_ACTOR where id = ?";

    ParameterizedRowMapper<Actor> mapper = new ParameterizedRowMapper<Actor>() {
    
        // notice the return type with respect to Java 5 covariant return types
        public Actor mapRow(ResultSet rs, int rowNum) throws SQLException {
            Actor actor = new Actor();
            actor.setId(rs.getLong("id"));
            actor.setFirstName(rs.getString("first_name"));
            actor.setLastName(rs.getString("last_name"));
            return actor;
        }
    };

    return this.simpleJdbcTemplate.queryForObject(sql, mapper, id);
}

請(qǐng)同樣參照第?11.2.1.2?節(jié) “JdbcTemplate 的最佳實(shí)踐”來(lái)獲取一些SimpleJdbcTemplate的最佳實(shí)踐

注意

SimpleJdbcTemplate只是提供了JdbcTemplate所提供的功能的子類(lèi)。 如果你需要使用JdbcTemplate的方法,而這些方法又沒(méi)有在SimpleJdbcTemplate中定義,你需要調(diào)用getJdbcOperations()方法 獲取相應(yīng)的方法調(diào)用。JdbcOperations接口中定義的方法需要在這邊做強(qiáng)制轉(zhuǎn)化才能使用。

11.2.4.?DataSource接口

為了從數(shù)據(jù)庫(kù)中取得數(shù)據(jù),我們首先需要獲取一個(gè)數(shù)據(jù)庫(kù)連接。Spring通過(guò)DataSource對(duì)象來(lái)完成這個(gè)工作。 DataSource是JDBC規(guī)范的一部分,它被視為一個(gè)通用的數(shù)據(jù)庫(kù)連接工廠。通過(guò)使用DataSource, Container或Framework可以將連接池以及事務(wù)管理的細(xì)節(jié)從應(yīng)用代碼中分離出來(lái)。 作為一個(gè)開(kāi)發(fā)人員,在開(kāi)發(fā)和測(cè)試產(chǎn)品的過(guò)程中,你可能需要知道連接數(shù)據(jù)庫(kù)的細(xì)節(jié)。但在產(chǎn)品實(shí)施時(shí),你不需要知道這些細(xì)節(jié)。通常數(shù)據(jù)庫(kù)管理員會(huì)幫你設(shè)置好數(shù)據(jù)源。

在使用Spring JDBC時(shí),你既可以通過(guò)JNDI獲得數(shù)據(jù)源,也可以自行配置數(shù)據(jù)源(使用Spring提供的DataSource實(shí)現(xiàn)類(lèi))。使用后者可以更方便的脫離Web容器來(lái)進(jìn)行單元測(cè)試。 這里我們將使用DriverManagerDataSource,不過(guò)DataSource有多種實(shí)現(xiàn), 后面我們會(huì)講到。使用DriverManagerDataSource和你以前獲取一個(gè)JDBC連接 的做法沒(méi)什么兩樣。你首先必須指定JDBC驅(qū)動(dòng)程序的全限定名,這樣DriverManager 才能加載JDBC驅(qū)動(dòng)類(lèi),接著你必須提供一個(gè)url(因JDBC驅(qū)動(dòng)而異,為了保證設(shè)置正確請(qǐng)參考相關(guān)JDBC驅(qū)動(dòng)的文檔), 最后你必須提供一個(gè)用戶(hù)連接數(shù)據(jù)庫(kù)的用戶(hù)名和密碼。下面我們將通過(guò)一個(gè)例子來(lái)說(shuō)明如何配置一個(gè)DriverManagerDataSource

DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("org.hsqldb.jdbcDriver");
dataSource.setUrl("jdbc:hsqldb:hsql://localhost:");
dataSource.setUsername("sa");
dataSource.setPassword("");

11.2.5.?SQLExceptionTranslator接口

SQLExceptionTranslator是一個(gè)接口,如果你需要在 SQLExceptionorg.springframework.dao.DataAccessException之間作轉(zhuǎn)換,那么必須實(shí)現(xiàn)該接口。 轉(zhuǎn)換器類(lèi)的實(shí)現(xiàn)可以采用一般通用的做法(比如使用JDBC的SQLState code),如果為了使轉(zhuǎn)換更準(zhǔn)確,也可以進(jìn)行定制(比如使用Oracle的error code)。

SQLErrorCodeSQLExceptionTranslator是SQLExceptionTranslator的默認(rèn)實(shí)現(xiàn)。 該實(shí)現(xiàn)使用指定數(shù)據(jù)庫(kù)廠商的error code,比采用SQLState更精確。轉(zhuǎn)換過(guò)程基于一個(gè)JavaBean(類(lèi)型為SQLErrorCodes)中的error code。 這個(gè)JavaBean由SQLErrorCodesFactory工廠類(lèi)創(chuàng)建,其中的內(nèi)容來(lái)自于 “sql-error-codes.xml”配置文件。該文件中的數(shù)據(jù)庫(kù)廠商代碼基于 Database MetaData 信息中的DatabaseProductName,從而配合當(dāng)前數(shù)據(jù)庫(kù)的使用。

SQLErrorCodeSQLExceptionTranslator使用以下的匹配規(guī)則:

  • 首先檢查是否存在完成定制轉(zhuǎn)換的子類(lèi)實(shí)現(xiàn)。通常SQLErrorCodeSQLExceptionTranslator 這個(gè)類(lèi)可以作為一個(gè)具體類(lèi)使用,不需要進(jìn)行定制,那么這個(gè)規(guī)則將不適用。

  • 接著將SQLException的error code與錯(cuò)誤代碼集中的error code進(jìn)行匹配。 默認(rèn)情況下錯(cuò)誤代碼集將從SQLErrorCodesFactory取得。 錯(cuò)誤代碼集來(lái)自classpath下的sql-error-codes.xml文件,它們將與數(shù)據(jù)庫(kù)metadata信息中的database name進(jìn)行映射。

  • 使用fallback翻譯器。SQLStateSQLExceptionTranslator類(lèi)是缺省的fallback翻譯器。

SQLErrorCodeSQLExceptionTranslator可以采用下面的方式進(jìn)行擴(kuò)展:

public class MySQLErrorCodesTranslator extends SQLErrorCodeSQLExceptionTranslator {

    protected DataAccessException customTranslate(String task, String sql, SQLException sqlex) {
        if (sqlex.getErrorCode() == -12345) {
            return new DeadlockLoserDataAccessException(task, sqlex);
        }
        return null;
    }
}

在上面的這個(gè)例子中,error code為'-12345'的SQLException將采用該轉(zhuǎn)換器進(jìn)行轉(zhuǎn)換,而其他的error code將由默認(rèn)的轉(zhuǎn)換器進(jìn)行轉(zhuǎn)換。 為了使用該轉(zhuǎn)換器,必須將其作為參數(shù)傳遞給JdbcTemplate類(lèi)的setExceptionTranslator方法,并在需要使用這個(gè)轉(zhuǎn)換器器的數(shù)據(jù) 存取操作中使用該JdbcTemplate。下面的例子演示了如何使用該定制轉(zhuǎn)換器:

// create a JdbcTemplate and set data source 
JdbcTemplate jt = new JdbcTemplate(); 
jt.setDataSource(dataSource); 
// create a custom translator and set the DataSource for the default translation lookup 
MySQLErrorCodesTransalator tr = new MySQLErrorCodesTransalator(); 
tr.setDataSource(dataSource); 
jt.setExceptionTranslator(tr); 
// use the JdbcTemplate for this SqlUpdate
SqlUpdate su = new SqlUpdate(); 
su.setJdbcTemplate(jt); 
su.setSql("update orders set shipping_charge = shipping_charge * 1.05"); 
su.compile(); 
su.update();

在上面的定制轉(zhuǎn)換器中,我們給它注入了一個(gè)數(shù)據(jù)源,因?yàn)槲覀內(nèi)匀恍枰? 使用默認(rèn)的轉(zhuǎn)換器從sql-error-codes.xml中獲取錯(cuò)誤代碼集。

11.2.6.?執(zhí)行SQL語(yǔ)句

我們僅需要非常少的代碼就可以達(dá)到執(zhí)行SQL語(yǔ)句的目的,一旦獲得一個(gè) DataSource和一個(gè)JdbcTemplate, 我們就可以使用JdbcTemplate提供的豐富功能實(shí)現(xiàn)我們的操作。下面的例子使用了極少的代碼完成創(chuàng)建一張表的工作。

import javax.sql.DataSource;
import org.springframework.jdbc.core.JdbcTemplate;

public class ExecuteAStatement {

    private JdbcTemplate jdbcTemplate;

    public void setDataSource(DataSource dataSource) {
        this.jdbcTemplate = new JdbcTemplate(dataSource);
    }

    public void doExecute() {
        this.jdbcTemplate.execute("create table mytable (id integer, name varchar(100))");
    }
}

11.2.7.?執(zhí)行查詢(xún)

除了execute方法之外,JdbcTemplate還提供了大量的查詢(xún)方法。 在這些查詢(xún)方法中,有很大一部分是用來(lái)查詢(xún)單值的。比如返回一個(gè)匯總(count)結(jié)果 或者從返回行結(jié)果中取得指定列的值。這時(shí)我們可以使用queryForInt(..)、 queryForLong(..)或者queryForObject(..)方法。 queryForObject方法用來(lái)將返回的JDBC類(lèi)型對(duì)象轉(zhuǎn)換成指定的Java對(duì)象,如果類(lèi)型轉(zhuǎn)換失敗將拋出 InvalidDataAccessApiUsageException異常。 下面的例子演示了兩個(gè)查詢(xún)的用法,一個(gè)返回int值,另一個(gè)返回String。

import javax.sql.DataSource;
import org.springframework.jdbc.core.JdbcTemplate;

public class RunAQuery {

    private JdbcTemplate jdbcTemplate;

    public void setDataSource(DataSource dataSource) {
        this.jdbcTemplate = new JdbcTemplate(dataSource);
    }
  
    public int getCount() {
        return this.jdbcTemplate.queryForInt("select count(*) from mytable");
    }

    public String getName() {
        return (String) this.jdbcTemplate.queryForObject("select name from mytable", String.class);
    }

    public void setDataSource(DataSource dataSource) {
        this.dataSource = dataSource;
    }
}

除了返回單值的查詢(xún)方法,JdbcTemplate還提供了一組返回List結(jié)果 的方法。List中的每一項(xiàng)對(duì)應(yīng)查詢(xún)返回結(jié)果中的一行。其中最簡(jiǎn)單的是queryForList方法, 該方法將返回一個(gè)List,該List中的每一條 記錄是一個(gè)Map對(duì)象,對(duì)應(yīng)應(yīng)數(shù)據(jù)庫(kù)中某一行;而該Map 中的每一項(xiàng)對(duì)應(yīng)該數(shù)據(jù)庫(kù)行中的某一列值。下面的代碼片斷接著上面的例子演示了如何用該方法返回表中所有記錄:

private JdbcTemplate jdbcTemplate;

public void setDataSource(DataSource dataSource) {
    this.jdbcTemplate = new JdbcTemplate(dataSource);
}

public List getList() {
    return this.jdbcTemplate.queryForList("select * from mytable");
}

返回的結(jié)果集類(lèi)似下面這種形式:

[{name=Bob, id=1}, {name=Mary, id=2}]

11.2.8.?更新數(shù)據(jù)庫(kù)

JdbcTemplate還提供了一些更新數(shù)據(jù)庫(kù)的方法。 在下面的例子中,我們根據(jù)給定的主鍵值對(duì)指定的列進(jìn)行更新。 例子中的SQL語(yǔ)句中使用了“?”占位符來(lái)接受參數(shù)(這種做法在更新和查詢(xún)SQL語(yǔ)句中很常見(jiàn))。 傳遞的參數(shù)值位于一個(gè)對(duì)象數(shù)組中(基本類(lèi)型需要被包裝成其對(duì)應(yīng)的對(duì)象類(lèi)型)。

import javax.sql.DataSource;

import org.springframework.jdbc.core.JdbcTemplate;

public class ExecuteAnUpdate {

    private JdbcTemplate jdbcTemplate;

    public void setDataSource(DataSource dataSource) {
        this.jdbcTemplate = new JdbcTemplate(dataSource);
    }

    public void setName(int id, String name) {
        this.jdbcTemplate.update(
                "update mytable set name = ? where id = ?", 
                new Object[] {name, new Integer(id)});
    }
}

11.2.9.?獲取自動(dòng)生成的主鍵

JdbcTemplate中有一個(gè)update方法,可以方便地從數(shù)據(jù)庫(kù)中獲取數(shù)據(jù)庫(kù)自動(dòng)創(chuàng)建的主鍵。(這是JDBC 3.0的標(biāo)準(zhǔn) - 可以參見(jiàn)13.6節(jié)獲取詳細(xì)信息)。 這個(gè)方法使用了PreparedStatementCreator接口作為第一個(gè)參數(shù), 可以通過(guò)這個(gè)接口的實(shí)現(xiàn)類(lèi)來(lái)定義相應(yīng)的Insert語(yǔ)句。另外一個(gè)參數(shù)是KeyHolder, 一旦update方法成功,這個(gè)參數(shù)將包含生成的主鍵。這里對(duì)于創(chuàng)建合適的PreparedStatement并沒(méi)有一個(gè)統(tǒng)一的標(biāo)準(zhǔn)。(這也解釋了函數(shù)簽名如此定義的原因)。下面是一個(gè)在Oracle上運(yùn)行良好的示例,它可能在其他平臺(tái)上無(wú)法工作:

final String INSERT_SQL = "insert into my_test (name) values(?)";
final String name = "Rob";

KeyHolder keyHolder = new GeneratedKeyHolder();
jdbcTemplate.update(
    new PreparedStatementCreator() {
        public PreparedStatement createPreparedStatement(Connection connection) throws SQLException {
            PreparedStatement ps =
                connection.prepareStatement(INSERT_SQL, new String[] {"id"});
            ps.setString(1, name);
            return ps;
        }
    },
    keyHolder);

// keyHolder.getKey() now contains the generated key
上一篇: 下一篇: