在經典的 JDBC 用法中, SQL 參數是用佔位符 ? 表示,而且受到位置的限制. 定位參數的問題在於, 一旦參數的順序發生變化, 就必須改變參數綁定. java
在 Spring JDBC 框架中, 綁定 SQL 參數的另外一種選擇是使用具名參數(named parameter).spring
那麼什麼是具名參數?sql
具名參數: SQL 按名稱(以冒號開頭)而不是按位置進行指定. 具名參數更易於維護, 也提高了可讀性. 具名參數由框架類在運行時用佔位符取代數據庫
具名參數只在 NamedParameterJdbcTemplate 中獲得支持。數組
在 SQL 語句中使用具名參數時, 能夠在一個 Map 中提供參數值, 參數名爲鍵app
也可使用 SqlParameterSource 參數框架
批量更新時能夠提供 Map 或 SqlParameterSource 的數組ide
如今,咱們在上一篇博客文章的例子的基礎上,繼續編寫代碼:性能
咱們在applicationContext.xml後面加入具名類對象的bean:this
配置文件:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.1.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd"> <!-- 自動掃描的包 --> <context:component-scan base-package="com.happBKs.spring.jdbcSpring"></context:component-scan> <!-- 導入資源文件 --> <context:property-placeholder location="classpath:db.properties" /> <!-- 配置c3p0數據源 --> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <property name="user" value="${jdbc.user}"></property> <property name="password" value="${jdbc.password}"></property> <property name="jdbcUrl" value="${jdbc.jdbcUrl}"></property> <property name="driverClass" value="${jdbc.driverClass}"></property> <property name="initialPoolSize" value="${jdbc.initPoolSize}"></property> <property name="maxPoolSize" value="${jdbc.maxPoolSize}"></property> </bean> <!-- 配置jdbc模板類 --> <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <property name="dataSource" ref="dataSource"></property> </bean> <!-- 配置 NamedParameterJdbcTemplate,該對象可使用具名參數。 但它沒有無參構造器,因此必須爲其制定構造參數,這裏指定的是出c3p0數據源 --> <bean id="namedParameterJdbcTemplate" class="org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate"> <constructor-arg ref="dataSource"></constructor-arg> </bean> </beans>
以後咱們再也不使用上次提到的EmployeeBean類,由於咱們已經知道了Spring JDBC並不能提供像Hibernate等ORM框架那樣的類屬性的級聯映射,因此咱們把屬性department改成了deptId。
package com.happBKs.spring.jdbcSpring; public class EmployeeBean2 { Integer id; String lastName; String email; Integer deptId; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public Integer getDeptId() { return deptId; } public void setDeptId(Integer deptId) { this.deptId = deptId; } public EmployeeBean2(Integer id, String lastName, String email, Integer deptId) { super(); this.id = id; this.lastName = lastName; this.email = email; this.deptId = deptId; } public EmployeeBean2() { super(); // TODO Auto-generated constructor stub } @Override public String toString() { return "EmployeeBean2 [id=" + id + ", lastName=" + lastName + ", email=" + email + ", deptId=" + deptId + "]"; } }
而後,咱們來使用具名參數來完成咱們以前提到的各類更新操做:
好比以前咱們插入一個記錄的寫法是:
這種寫法,賦值的參數沒有給予具體的名稱,只經過佔位符?來完成佔位,經過賦值參數的順序來對應相應的參數。如今咱們能夠藉助於org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate來幫助咱們解決這個問題:
不過這裏有兩種方法,咱們先介紹最通常的一種:
/* * 能夠爲參數取名字:ln,:email,:deptid * 優勢:若是有多個參數,不用去糾結於參數的位置順序,直接對應參數名,便於維護 * 缺點:較爲麻煩 */ @Test public void testNamedParameterJdbcTemplate(){ //以前不適用具名參數的用法: //String sql="insert employee(last_name,email,dept_id) values(?,?,?)"; //咱們給予參數賦值必須依賴於?的順序 // 使用具名參數的用法: String sql="insert employee(last_name,email,dept_id) values(:ln,:email,:deptid)"; Map<String,Object> paramMap=new HashMap<String, Object>(); paramMap.put("ln", "超級無敵銀河最強臨時工"); paramMap.put("email", "super@qq.com"); paramMap.put("deptid", 4); namedParameterJdbcTemplate.update(sql,paramMap); }
這裏,SQL語句中的賦值參數被用":"的形式給出,這裏就是具名參數。而後咱們能夠經過一個Map對象,Map的key是咱們的具名參數,而value則是參數的值,而後經過NamedParameterJdbcTemplate類對象的方法update來完成曾刪改操做。
運行結果:
不過,這種方法仍是有比較麻煩的地方,咱們須要在map對象中逐一指定參數。
這時候,你可能不由感慨,仍是ORM框架好,類屬屬性可以自動與數據庫表的字段映射。這裏Spring JDBC在具名參數賦值時也考慮了相似的解決方法。
下面,我來介紹具名參數的第二種方法:
咱們須要將具名參數定義爲與類的屬性名稱同樣的名字,而後,能夠建立一個相應的類的對象,並調用相應屬性的set方法賦值,以後,咱們就調用update的另外一個重載方法:
/* * 使用具名參數時,可使用int org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate.update(String sql, SqlParameterSource paramSource) throws DataAccessException 方法進行更新操做: 1. SQL語句中的具名參數與類的屬性名一致 2. 使用接口SqlParameterSource的BeanPropertySqlParameterSource實現類做爲參數 */ @Test public void testNamedParameterJdbcTemplate2(){ //以前不適用具名參數的用法: //String sql="insert employee(last_name,email,dept_id) values(?,?,?)"; //咱們給予參數賦值必須依賴於?的順序 // 使用具名參數的用法: String sql="insert employee(last_name,email,dept_id) values(:lastName,:email,:deptId)"; EmployeeBean2 e=new EmployeeBean2(); e.setLastName("haha"); e.setEmail("haha@qq.com"); e.setDeptId(4); SqlParameterSource sqlParameterSource=new BeanPropertySqlParameterSource(e); namedParameterJdbcTemplate.update(sql,sqlParameterSource); }
運行結果: