以C3P0連接池為例:由於C3P0是第三方,我們無法使用注解將其定義為bean,因此需要在applicationContext.xml中配置:

1 <!-- 導入配置文件 --> 2 <context:property-placeholder location="classpath:dataSource.properties"/> 3 <aop:aspectj-autoproxy proxy-target-class="true"/> 4 <bean id="dataSourceLocal" name="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> 5 <!-- 指定連接數據庫的驅動--> 6 <property name="driverClass" value="${jdbc.driverClassName}"/> 7 <!-- 指定連接數據庫的URL--> 8 <property name="jdbcUrl" value="${jdbc.url}"/> 9 <!-- 指定連接數據庫的用戶名--> 10 <property name="user" value="${jdbc.username}"/> 11 <!-- 指定連接數據庫的密碼--> 12 <property name="password" value="${jdbc.password}"/> 13 <!-- 指定連接池中保留的最大連接數. Default:15--> 14 <property name="maxPoolSize" value="${jdbc.maxPoolSize}"/> 15 <!-- 指定連接池中保留的最小連接數--> 16 <property name="minPoolSize" value="${jdbc.minPoolSize}"/> 17 <!-- 指定連接池的初始化連接數 取值應在minPoolSize 與 maxPoolSize 之間.Default:3--> 18 <property name="initialPoolSize" value="${jdbc.initialPoolSize}"/> 19 <!-- 最大空閑時間,60秒內未使用則連接被丟棄。若為0則永不丟棄。 Default:0--> 20 <property name="maxIdleTime" value="${jdbc.maxIdleTime}"/> 21 <!-- 當連接池中的連接耗盡的時候c3p0一次同時獲取的連接數. Default:3--> 22 <property name="acquireIncrement" value="${jdbc.acquireIncrement}"/> 23 <!-- JDBC的標准,用以控制數據源內加載的PreparedStatements數量。 24 但由於預緩存的statements屬於單個connection而不是整個連接池所以設置這個參數需要考慮到多方面的因數.如果maxStatements與maxStatementsPerConnection均為0,則緩存被關閉。Default:0--> 25 <property name="maxStatements" value="${jdbc.maxStatements}"/> 26 <!-- 每60秒檢查所有連接池中的空閑連接.Default:0 --> 27 <property name="idleConnectionTestPeriod" value="${jdbc.idleConnectionTestPeriod}"/> 28 </bean>
可以看到,連接配置中引用了<context:property-placeholder location="classpath:dataSource.properties"/>標簽,這是說從外部配置文件中讀取數據庫相關的數據,用${}表達式可以讀取,因此,我們需要同時配置dataSource.properties文件,內容如下:

1 jdbc.driverClassName=oracle.jdbc.driver.OracleDriver 2 jdbc.url=jdbc:oracle:thin:@localhost:1521:orcl 3 jdbc.username=scott 4 jdbc.password=orcl 5 jdbc.initialPoolSize=20 6 jdbc.maxPoolSize=100 7 jdbc.minPoolSize=10 8 jdbc.maxIdleTime=600 9 jdbc.acquireIncrement=5 10 jdbc.maxStatements=5 11 jdbc.idleConnectionTestPeriod=60
只要保證配置文件正確,數據庫的連接配置也就完成了,接下來需要配置JDBCTemplate,仍然是在applicationContext.xml中配置:

1 <!-- 配置jdbcTemplate --> 2 <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> 3 <property name="dataSource" ref="dataSourceLocal"></property> 4 </bean>
JDBCTemplate類中,只有一個參數,那就是dataSource,因此需要注入上面的dateSource。
接下來以Oracle中Scott用戶下的dept表為例測試:

1 private ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml"); 2 private JdbcTemplate jt=(JdbcTemplate) ctx.getBean("jdbcTemplate");

1 @Test 2 public void updateTest(){ 3 String sqlUpdate="update emp set ename=? where empno=?"; 4 jt.update(sqlUpdate,"SMITH",7369); 5 }
可以看到,此處在sql語句中使用了?作為占位符,在JDBCTemplate的update方法中一一對應定義即可。
另外,JDBCTemplate同時支持批量操作,代碼如下:

1 @Test 2 public void testBatchUpdate(){ 3 //批量修改 4 String[] s=new String[]{"update emp set ename='SMITH1' where empno=7369","update emp set ename='SMITH' where empno=7369"}; 5 jt.batchUpdate(s); 6 //批量添加 7 List<Object[]> addList = new ArrayList<Object[]>(); 8 addList.add(new Object[]{52,"AA","SHANGHAI"}); 9 addList.add(new Object[]{62,"BB","BEIJING"}); 10 addList.add(new Object[]{72,"CC","XI'AN"}); 11 addList.add(new Object[]{82,"DD","HANGZHOU"}); 12 jt.batchUpdate("insert into scott.dept values (?,?,?)",addList); 13 //批量刪除 14 List<Object[]> delList = new ArrayList<Object[]>(); 15 delList.add(new Integer[]{40}); 16 jt.batchUpdate("delete dept where deptno>?",delList); 17 }
批量操作需要用到batchUpdate方法,其重載形式如下:
我們使用了第一和第三種方法就夠用了。
查詢分為單條數據查詢和多條數據查詢,JDBCTemplate支持使用RowMapper類將其對應到相應的實體類,如果是單條數據,可使用queryForObject方法:

1 @Test 2 public void testQueryForObject(){ 3 String sql="select deptno,dname,loc from dept where deptno=?"; 4 RowMapper<Dept> rm=new BeanPropertyRowMapper<Dept>(Dept.class); 5 Dept d=jt.queryForObject(sql,rm,20); 6 System.err.println(d); 7 }
如果是多條數據,可以用query方法:

1 @Test 2 public void testQueryForList(){ 3 String sql="select * from dept where deptno>?"; 4 RowMapper<Dept> re=new BeanPropertyRowMapper<Dept>(Dept.class); 5 List<Dept> dept=jt.query(sql, re,20); 6 System.out.println(dept); 7 }
另外,也支持統計查詢和單列查詢:

1 @Test 2 public void testQueryColumnOrCount(){ 3 //獲取統計信息 4 String sql="select count(empno) from emp"; 5 Long l=jt.queryForObject(sql, Long.class); 6 System.err.println(l); 7 //獲取單列信息 8 String sql4Date="select hiredate from emp"; 9 RowMapper<Date> re=new BeanPropertyRowMapper<Date>(Date.class); 10 List<Date> d=jt.query(sql4Date, re); 11 System.err.println(d); 12 }
從上面的例子中可以看到,參數都是通過?占位符順序一一對應傳遞參數的,如果參數位置變動,那么JDBC操作需要同時變更,不安全且工作量大,因此Spring同時提供了NamedParameterJDBCTemplate具名參數:SQL 按名稱(以冒號開頭)而不是按位置進行指定.。
優勢:具名參數更易於維護, 也提升了可讀性.
與JDBCTemplate一樣,需要在XML中配置:

1 <!-- 配置NamedParameterJDBCTemplate --> 2 <bean id="namedParameterJDBCTemplate" class="org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate"> 3 <constructor-arg><ref bean="dataSourceLocal"/></constructor-arg> 4 </bean>
用法:
在 SQL 語句中使用具名參數時, 可以在一個 Map 中提供參數值, 參數名為鍵
也可以使用 SqlParameterSource 參數
批量更新時可以提供 Map 或 SqlParameterSource 的數組
代碼如下:

1 /** 2 * NamedParameterJDBCTemplate用法測試,以update為例 3 */ 4 @Test 5 public void testNamedParameterJDBCTemplate(){ 6 String sql="insert into dept values (:deptno,:dname,:loc)";//此處參數是可以自由命名的 7 Map<String, Object> map=new HashMap<String, Object>(); 8 map.put("deptno", 94); 9 map.put("dname", "管理部"); 10 map.put("loc", "金華"); 11 npjt.update(sql, map); 12 } 13 /** 14 * 使用SqlParameterSource類與實體類對應,此時參數命名需與實體類屬性名對應 15 * SqlParameterSource sps = new BeanPropertySqlParameterSource(對象) 16 */ 17 @Test 18 public void testNamedParameterJDBCTemplateByEntity(){ 19 String sql="insert into dept values (:deptno,:dname,:loc)";//此處參數命名需與實體類屬性名相同 20 SqlParameterSource sps=new BeanPropertySqlParameterSource(new Dept(88, "業務部", "北京")); 21 npjt.update(sql, sps); 22 }
高級用法參考:Spring框架筆記(二十五)——NamedParameterJdbcTemplate與具名參數
總結:JDBCTemplate很強大,但畢竟不是ORM框架,比如,並不支持級聯操作。