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

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

11.5.?通過使用SimpleJdbc類簡化JDBC操作

SimpleJdbcInsert類和SimpleJdbcCall類主要利用了JDBC驅動所提供的數據庫元數據的一些特性來簡化數據庫操作配置。 這意味著你可以盡可能的簡化你的數據庫操作配置。當然,你可以可以將元數據處理的特性關閉,從而在你的代碼中詳細指定這些特性。

11.5.1.?使用SimpleJdbcInsert插入數據

讓我們從SimpleJdbcInsert類開始。我們將盡可能使用最少量的配置。SimpleJdbcInsert類必須在數據訪問層的初始化方法中被初始化。 在這個例子中,初始化方法為setDataSource方法。你無需繼承自SimpleJdbcInsert 類,只需要創(chuàng)建一個新的實例,并通過withTableName方法設置table名稱。 這個類使用了“fluid”模式返回SimpleJdbcInsert,從而你可以訪問到所有的可以進行配置的方法。在這個例子中,我們只使用了一個方法,稍后我們會看到更多的配置方法。

public class JdbcActorDao implements ActorDao {
    private SimpleJdbcTemplate simpleJdbcTemplate;
    private SimpleJdbcInsert insertActor;

    public void setDataSource(DataSource dataSource) {
        this.simpleJdbcTemplate = new SimpleJdbcTemplate(dataSource);
        this.insertActor = 
                new SimpleJdbcInsert(dataSource).withTableName("t_actor");
    }

    public void add(Actor actor) {
        Map<String, Object> parameters = new HashMap<String, Object>(3);
        parameters.put("id", actor.getId());
        parameters.put("first_name", actor.getFirstName());
        parameters.put("last_name", actor.getLastName());
        insertActor.execute(parameters);
    }

    //  ... additional methods
}

這個方法通過接收 java.utils.Map 作為它唯一的參數。 在這里需要重點注意的是,在Map中的所有的key,必須和數據庫中定義的列名完全匹配。這是因為我們是通過讀取元數據來構造實際的Insert語句的。

11.5.2.?使用SimpleJdbcInsert來獲取自動生成的主鍵

接下來,我們對于同樣的插入語句,我們并不傳入id,而是通過數據庫自動獲取主鍵的方式來創(chuàng)建新的Actor對象并插入數據庫。 當我們創(chuàng)建SimpleJdbcInsert實例時, 我們不僅需要指定表名,同時我們通過usingGeneratedKeyColumns方法指定需要數據庫自動生成主鍵的列名。

public class JdbcActorDao implements ActorDao {
    private SimpleJdbcTemplate simpleJdbcTemplate;
    private SimpleJdbcInsert insertActor;

    public void setDataSource(DataSource dataSource) {
        this.simpleJdbcTemplate = new SimpleJdbcTemplate(dataSource);
        this.insertActor =
                new SimpleJdbcInsert(dataSource)
                        .withTableName("t_actor")
                        .usingGeneratedKeyColumns("id");
    }

    public void add(Actor actor) {
        Map<String, Object> parameters = new HashMap<String, Object>(2);
        parameters.put("first_name", actor.getFirstName());
        parameters.put("last_name", actor.getLastName());
        Number newId = insertActor.executeAndReturnKey(parameters);
        actor.setId(newId.longValue());
    }

    //  ... additional methods
}

這樣我們可以看到與之前執(zhí)行的insert操作的不同之處在于,我們無需添加id到參數的Map中去,只需要調用executeReturningKey方法。 這個方法將返回一個java.lang.Number對象,我們可以使用這個對象來創(chuàng)建一個字符類型的實例作為我們的域模型的屬性。 有一點很重要的地方需要注意,我們無法依賴所有的數據庫來返回我們指定的Java類型,因為我們只知道這些對象的基類是java.lang.Number。 如果你有聯(lián)合主鍵或者那些非數字類型的主鍵需要生成,那么你可以使用executeReturningKeyHolder方法返回的KeyHolder對象。

11.5.3.?指定SimpleJdbcInsert所使用的字段

通過指定所使用的字段名稱,可以使SimpleJdbcInsert僅使用這些字段作為insert語句所使用的字段。這可以通過usingColumns方法進行配置。

public class JdbcActorDao implements ActorDao {
    private SimpleJdbcTemplate simpleJdbcTemplate;
    private SimpleJdbcInsert insertActor;

    public void setDataSource(DataSource dataSource) {
        this.simpleJdbcTemplate = new SimpleJdbcTemplate(dataSource);
        this.insertActor =
                new SimpleJdbcInsert(dataSource)
                        .withTableName("t_actor")
                        .usingColumns("first_name", "last_name")
                        .usingGeneratedKeyColumns("id");
    }

    public void add(Actor actor) {
        Map<String, Object> parameters = new HashMap<String, Object>(2);
        parameters.put("first_name", actor.getFirstName());
        parameters.put("last_name", actor.getLastName());
        Number newId = insertActor.executeAndReturnKey(parameters);
        actor.setId(newId.longValue());
    }

    //  ... additional methods
}

執(zhí)行這樣的insert語句所使用的字段,與之前我們所依賴的數據庫元數據是一致的。

11.5.4.?使用SqlParameterSource提供參數值

使用Map來指定參數值有時候工作得非常好,但是這并不是最簡單的使用方式。Spring提供了一些其他的SqlParameterSource實現類來指定參數值。 我們首先可以看看BeanPropertySqlParameterSource類,這是一個非常簡便的指定參數的實現類,只要你有一個符合JavaBean規(guī)范的類就行了。它將使用其中的getter方法來獲取參數值。 下面是一個例子:

public class JdbcActorDao implements ActorDao {
    private SimpleJdbcTemplate simpleJdbcTemplate;
    private SimpleJdbcInsert insertActor;

    public void setDataSource(DataSource dataSource) {
        this.simpleJdbcTemplate = new SimpleJdbcTemplate(dataSource);
        this.insertActor =
                new SimpleJdbcInsert(dataSource)
                        .withTableName("t_actor")
                        .usingGeneratedKeyColumns("id");
    }

    public void add(Actor actor) {
        SqlParameterSource parameters = new BeanPropertySqlParameterSource(actor);
        Number newId = insertActor.executeAndReturnKey(parameters);
        actor.setId(newId.longValue());
    }

    //  ... additional methods
}

另外一個實現類:MapSqlParameterSource也使用Map來指定參數,但是他另外提供了一個非常簡便的addValue方法,可以被連續(xù)調用,來增加參數。

public class JdbcActorDao implements ActorDao {
    private SimpleJdbcTemplate simpleJdbcTemplate;
    private SimpleJdbcInsert insertActor;

    public void setDataSource(DataSource dataSource) {
        this.simpleJdbcTemplate = new SimpleJdbcTemplate(dataSource);
        this.insertActor =
                new SimpleJdbcInsert(dataSource)
                        .withTableName("t_actor")
                        .usingGeneratedKeyColumns("id");
    }

    public void add(Actor actor) {
        SqlParameterSource parameters = new MapSqlParameterSource()
                .addValue("first_name", actor.getFirstName())
                .addValue("last_name", actor.getLastName());
        Number newId = insertActor.executeAndReturnKey(parameters);
        actor.setId(newId.longValue());
    }

    //  ... additional methods
}

正如你看到的,配置是一樣的,區(qū)別只是切換了不同的提供參數的實現方式來執(zhí)行調用。

11.5.5.?使用SimpleJdbcCall調用存儲過程

接下來我們把我們的關注點放在使用 SimpleJdbcCall 來進行存儲過程的調用上。 設計這個類的目的在于使得調用存儲過程盡可能簡單。它同樣利用的數據庫元數據的特性來查找傳入的參數和返回值。 這意味著你無需明確聲明那些參數。當然,如果你喜歡,可以依然聲明這些參數,尤其對于某些參數,你無法直接將他們映射到Java類上,例如ARRAY類型和STRUCT類型的參數。 在我們的第一個示例中,我們可以看到一個簡單的存儲過程調用,它僅僅返回VARCHAR和DATE類型。 這里,我特地為Actor類增加了一個birthDate的屬性,從而可以使得返回值擁有不同的數據類型。 這個存儲過程讀取actor的主鍵,并返回first_name,last_name,和birth_date字段作為返回值。 下面是這個存儲過程的源碼,它可以工作在MySQL數據庫上:

CREATE PROCEDURE read_actor ( 
  IN in_id INTEGER, 
  OUT out_first_name VARCHAR(100), 
  OUT out_last_name VARCHAR(100), 
  OUT out_birth_date DATE) 
BEGIN 
  SELECT first_name, last_name, birth_date 
  INTO out_first_name, out_last_name, out_birth_date 
  FROM t_actor where id = in_id;
END;

正如你看到的,這里有四個參數,其中一個是傳入的參數“in_id”,表示了Actor的主鍵,剩下的參數是作為讀取數據庫表中的數據所返回的返回值。

SimpleJdbcCall的聲明與SimpleJdbcInsert類似,你無需繼承這個類,而只需要在初始化方法中進行初始化。 在這里例子中,我們只需要指定存儲過程的名稱。

public class JdbcActorDao implements ActorDao {
    private SimpleJdbcTemplate simpleJdbcTemplate;
    private SimpleJdbcCall procReadActor;

    public void setDataSource(DataSource dataSource) {
        this.simpleJdbcTemplate = new SimpleJdbcTemplate(dataSource);
        this.procReadActor =
                new SimpleJdbcCall(dataSource)
                        .withProcedureName("read_actor");
    }

    public Actor readActor(Long id) {
        SqlParameterSource in = new MapSqlParameterSource()
                .addValue("in_id", id); 
        Map out = procReadActor.execute(in);
        Actor actor = new Actor();
        actor.setId(id);
        actor.setFirstName((String) out.get("out_first_name"));
        actor.setLastName((String) out.get("out_last_name"));
        actor.setBirthDate((Date) out.get("out_birth_date"));
        return actor;
    }

    //  ... additional methods
}

通過SimpleJdbcCall執(zhí)行存儲過程需要創(chuàng)建一個SqlParameterSource的實現類來指定傳入的參數。 需要注意的是,傳入參數的名稱與存儲過程中定義的名稱必須保持一致。這里,我們無需保持一致,因為我們使用數據庫的元數據信息來決定我們需要什么樣的數據庫對象。 當然,你在源代碼中所指定的名稱可能和數據庫中完全不同,有的數據庫會把這些名稱全部轉化成大寫,而有些數據庫會把這些名稱轉化為小寫。

execute方法接收傳入的參數,并返回一個Map作為返回值,這個Map包含所有在存儲過程中指定的參數名稱作為key。 在這個例子中,他們分別是out_first_name,out_last_nameout_birth_date。

execute方法的最后部分是使用存儲過程所返回的值創(chuàng)建一個新的Actor實例。 同樣的,這里我們將名稱與存儲過程中定義的名稱保持一致非常重要。在這個例子中,在返回的Map中所定義的key值和數據庫的存儲過程中定義的值一致。 你可能需要在這里指定Spring使用Jakarta Commons提供的CaseInsensitiveMap。這樣做,你需要在創(chuàng)建你自己的JdbcTemplate類時,設置setResultsMapCaseInsensitive屬性為True。 然后,你將這個自定義的JdbcTemplate傳入SimpleJdbcCall的構造函數。當然,你需要把commons-collections.jar加入到classpath中去。 下面是配置示例:

public class JdbcActorDao implements ActorDao {
    private SimpleJdbcCall procReadActor;

    public void setDataSource(DataSource dataSource) {
        JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
        jdbcTemplate.setResultsMapCaseInsensitive(true);
        this.procReadActor =
                new SimpleJdbcCall(jdbcTemplate)
                        .withProcedureName("read_actor");
    }


    //  ... additional methods
}

通過這樣的配置,你就可以無需擔心返回參數值的大小寫問題。

11.5.6.?聲明SimpleJdbcCall使用的參數

你已經看到如何通過元數據來簡化參數配置,但是你也可以明確地指定這些參數??梢栽趧?chuàng)建SimpleJdbcCall時,通過使用declareParameters方法來聲明參數。 這個方法接收一組SqlParameter對象作為參數。我們可以參照下一個章節(jié),如何創(chuàng)建SqlParameter。

我們可以有選擇性的顯示聲明一個、多個、甚至所有的參數。參數元數據在這里會被同時使用。 通過調用withoutProcedureColumnMetaDataAccess方法,我們可以指定數據庫忽略所有的元數據處理并使用顯示聲明的參數。 另外一種情況是,其中的某些參數值具有默認的返回值,我們需要在返回值中指定這些返回值。為了實現這個特性,我們可以使用useInParameterNames來指定一組需要被包含的參數名稱。

這是一個完整的聲明存儲過程調用的例子:

public class JdbcActorDao implements ActorDao {
    private SimpleJdbcCall procReadActor;

    public void setDataSource(DataSource dataSource) {
        JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
        jdbcTemplate.setResultsMapCaseInsensitive(true);
        this.procReadActor =
                new SimpleJdbcCall(jdbcTemplate)
                        .withProcedureName("read_actor")
                        .withoutProcedureColumnMetaDataAccess()
                        .useInParameterNames("in_id")
                        .declareParameters(
                                new SqlParameter("in_id", Types.NUMERIC),
                                new SqlOutParameter("out_first_name", Types.VARCHAR),
                                new SqlOutParameter("out_last_name", Types.VARCHAR),
                                new SqlOutParameter("out_birth_date", Types.DATE)
                        );
    }


    //  ... additional methods
}

執(zhí)行和最終的返回處理是相同的,我們在這里只是明確聲明了參數類型,而不是依賴數據庫元數據特性。 這一點很重要,尤其對于那些數據庫并不支持元數據的情況。當前,我們支持元數據的特性的數據包含:Apache Derby、DB2、MySQL、 Microsoft SQL Server、Oracle和Sybase。我們同時對某些數據庫內置函數支持元數據特性:MySQL、Microsoft SQL Server和Oracle。

11.5.7.?如何定義SqlParameters

為SimpleJdbc類或者后續(xù)章節(jié)提到的RDBMS操作指定參數,你需要使用SqlParameter或者他的子類。 你可以通過指定參數名稱以及對應的SQL類型并傳入構造函數作為參數來指定SqlParameter,其中,SQL類型是java.sql.Types中所定義的常量。 我們已經看到過類似的聲明:

   new SqlParameter("in_id", Types.NUMERIC),
   new SqlOutParameter("out_first_name", Types.VARCHAR),

第一行的SqlParameter定義了一個傳入參數。傳入參數可以在所有的存儲過程中使用,也可以在稍后章節(jié)中提到的SqlQuery類及其子類中使用。

第二行SqlOutParameter定義了一個返回值。它可以被存儲過程調用所使用。當然,還有一個SqlInOutParameter類,可以用于輸入輸出參數。 也就是說,它既是一個傳入參數,也是一個返回值。

除了參數名稱和SQL類型,你還可以聲明一些其他額外的選項。對于傳入參數,你可以為numeric數據類型指定精度,或者對于特定的數據庫指定特殊類型。 對于返回值,你可以提供一個RowMapper接口來處理所有從REF cursor返回的列。另外一個選項是指定一個SqlReturnType類,從而可以定制返回值的處理方式。

11.5.8.?使用SimpleJdbcCall調用內置函數

內置函數的調用幾乎和存儲過程的調用是一樣的。唯一的不同在于,你需要聲明的是一個函數的名稱而不是存儲過程的名稱。 這可以通過withFunctionName方法來完成。使用這個方法,表明你的調用是一個函數。你所指定的這個函數名稱將被作為調用對象。 同時有一個叫做executeFunction的方法,將獲得特定的Java類型的函數調用的返回值。 此時,你無需通過返回的Map來獲取返回值。另外有一個類似的便捷方法executeObject用于存儲過程,但是他只能處理單個返回值的情況。 下面的示例展示了一個叫做get_actor_name 的函數調用,返回actor的完整的名稱。 這個函數將工作在MySQL數據庫上。

CREATE FUNCTION get_actor_name (in_id INTEGER)
RETURNS VARCHAR(200) READS SQL DATA 
BEGIN
  DECLARE out_name VARCHAR(200);
  SELECT concat(first_name, ' ', last_name)
    INTO out_name
    FROM t_actor where id = in_id;
  RETURN out_name;
END;

調用這個函數,我們依然在初始化方法中創(chuàng)建SimpleJdbcCall

public class JdbcActorDao implements ActorDao {
    private SimpleJdbcTemplate simpleJdbcTemplate;
    private SimpleJdbcCall funcGetActorName;

    public void setDataSource(DataSource dataSource) {
        this.simpleJdbcTemplate = new SimpleJdbcTemplate(dataSource);
        JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
        jdbcTemplate.setResultsMapCaseInsensitive(true);
        this.funcGetActorName =
                new SimpleJdbcCall(jdbcTemplate)
                        .withFunctionName("get_actor_name");
    }

    public String getActorName(Long id) {
        SqlParameterSource in = new MapSqlParameterSource()
                .addValue("in_id", id); 
        String name = funcGetActorName.executeFunction(String.class, in);
        return name;
    }

    //  ... additional methods
}

被調用的函數返回一個String類型。

11.5.9.?使用SimpleJdbcCall返回的ResultSet/REF Cursor

期望通過調用存儲過程或者函數來返回ResultSet一直是一個問題。一些數據庫在JDBC結果處理中返回結果集,而另外一些數據庫則需要明確指定返回值的類型。 無論哪種方法,都需要在循環(huán)遍歷結果集時,做出一些額外的工作,從而處理每一條記錄。 通過SimpleJdbcCall,你可以使用returningResultSet方法,并定義一個RowMapper的實現類來處理特定的返回值。 當結果集在返回結果處理過程中沒有被定義名稱時,返回的結果集必須與定義的RowMapper的實現類指定的順序保持一致。 而指定的名字也會被用作返回結果集中的名稱。

在這個例子中,我們將使用一個存儲過程,它并不接收任何參數,返回t_actor表中的所有的行,下面是MySQL數據庫中的存儲過程源碼:

CREATE PROCEDURE read_all_actors()
BEGIN
 SELECT a.id, a.first_name, a.last_name, a.birth_date FROM t_actor a;
END;

要調用這個存儲過程,我們需要定義一個RowMapper的實現類。我們所使用的類遵循JavaBean的規(guī)范,所以我們可以使用ParameterizedBeanPropertyRowMapper作為實現類。 通過將相應的class類作為參數傳入到newInstance方法中,我們可以創(chuàng)建這個實現類。

public class JdbcActorDao implements ActorDao {
    private SimpleJdbcTemplate simpleJdbcTemplate;
    private SimpleJdbcCall procReadAllActors;

    public void setDataSource(DataSource dataSource) {
        this.simpleJdbcTemplate = new SimpleJdbcTemplate(dataSource);
        JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
        jdbcTemplate.setResultsMapCaseInsensitive(true);
        this.procReadAllActors =
                new SimpleJdbcCall(jdbcTemplate)
                        .withProcedureName("read_all_actors")
                        .returningResultSet("actors",
                                ParameterizedBeanPropertyRowMapper.newInstance(Actor.class));
    }

    public List getActorsList() {
        Map m = procReadAllActors.execute(new HashMap<String, Object>(0));
        return (List) m.get("actors");
    }

    //  ... additional methods
}

這個函數調用傳入一個空的Map進入,因為這里不需要任何的參數傳入。而函數調用所返回的結果集將返回的是Actors列表。

?? ??: ?? ??: