Spring3核心技術之JdbcTemplate
Spring通過抽象JDBC訪問並提供一致的API來簡化JDBC編程的工作量。我們只需要聲明SQL、調用合適的Spring JDBC框架API、處理結果集即可。事務由Spring管理,並將JDBC受查異常轉換爲Spring一致的非受查異常,從而簡化開發。
- ....
- Connection conn = null;
- PreparedStatement pstmt = null;
- try {
- conn = getConnection(); //1.獲取JDBC連接
- String sql = "select * from tableName"; //2.聲明SQL
- pstmt = conn.prepareStatement(sql); //3.預編譯SQL
- ResultSet rs = pstmt.executeQuery(); //4.執行SQL
- process(rs); //5.處理結果集
- closeResultSet(rs); //5.釋放結果集
- closeStatement(pstmt); //6.釋放Statement
- conn.commit(); //8.提交事務
- } catch (Exception e) {
- //9.處理異常並回滾事務
- conn.rollback();
- throw e;
- } finally {
- //10.釋放JDBC連接,防止JDBC連接不關閉造成的內存泄漏
- closeConnection(conn);
- }
- ....
以上代碼片段具有冗長、重複、容易忘記某一步驟從而導致出錯、顯示控制事務、顯示處理受檢查異常等等。
Spring主要提供JDBC模板方式、關係數據庫對象化方式和SimpleJdbc方式三種方式來簡化JDBC編程,這三種方式就是Spring JDBC的工作模式:
Spring JDBC抽象框架core包提供了JDBC模板類,其中JdbcTemplate是core包的核心類,所以其他模板類都是基於它封裝完成的,JDBC模板類是第一種工作模式。
JdbcTemplate類通過模板設計模式幫助我們消除了冗長的代碼,只做需要做的事情(即可變部分),並且幫我們做哪些固定部分,如連接的創建及關閉。
- JDBC模板方式:Spring JDBC框架提供以下幾種模板類來簡化JDBC編程,實現GoF模板設計模式,將可變部分和非可變部分分離,可變部分採用回調接口方式由用戶來實現:如JdbcTemplate、NamedParameterJdbcTemplate、SimpleJdbcTemplate。
- 關係數據庫操作對象化方式:Spring JDBC框架提供了將關係數據庫操作對象化的表示形式,從而使用戶可以採用面向對象編程來完成對數據庫的訪問;如MappingSqlQuery、SqlUpdate、SqlCall、SqlFunction、StoredProcedure等類。這些類的實現一旦建立即可重用並且是線程安全的。
- SimpleJdbc方式:Spring JDBC框架還提供了SimpleJdbc方式來簡化JDBC編程,SimpleJdbcInsert 、 SimpleJdbcCall用來簡化數據庫表插入、存儲過程或函數訪問。
Spring的JDBC架構
Spring JDBC抽象框架由四部分組成:datasource、support、core、object如圖所示。
- support包:提供將JDBC異常轉換爲DAO非檢查異常轉換類、一些工具類如JdbcUtils等。
- datasource包:提供簡化訪問JDBC 數據源(javax.sql.DataSource實現)工具類,並提供了一些DataSource簡單實現類從而能使從這些DataSource獲取的連接能自動得到Spring管理事務支持。
- core包:提供JDBC模板類實現及可變部分的回調接口,還提供SimpleJdbcInsert等簡單輔助類。
- object包:提供關係數據庫的對象表示形式,如MappingSqlQuery、SqlUpdate、SqlCall、SqlFunction、StoredProcedure等類,該包是基於core包JDBC模板類實現。
SpringJDbc工程中需要引入以下JAR包:
Spring JDBC提供如下DaoSupport實現:
● JdbcDaoSupport:用於支持一致的JdbcTemplate訪問;
● NamedParameterJdbcDaoSupport:繼承JdbcDaoSupport,同時提供NamedParameterJdbcTemplate訪問;
● SimpleJdbcDaoSupport:繼承JdbcDaoSupport,同時提供SimpleJdbcTemplate訪問。
由於JdbcTemplate、NamedParameterJdbcTemplate、SimpleJdbcTemplate類使用DataSourceUtils獲取及釋放連接,而且連接是與線程綁定的,因此這些JDBC模板類是線程安全的,即JdbcTemplate對象可以在多線程中重用
JdbcTemplate
JdbcTemplate主要提供以下五類方法:
- execute():可以用於執行任何SQL語句,一般用於執行DDL語句;
- update()及batchUpdate():update方法用於執行新增、修改、刪除等語句;batchUpdate方法用於執行批處理相關語句;
- query()及queryForXXX():用於執行查詢相關語句;
- call():用於執行存儲過程、函數相關語句。
JdbcTemplate類支持的回調類:
● 預編譯語句及存儲過程創建回調:用於根據JdbcTemplate提供的連接創建相應的語句;
PreparedStatementCreator:通過回調獲取JdbcTemplate提供的Connection,由用戶使用該Conncetion創建相關的PreparedStatement;
CallableStatementCreator:通過回調獲取JdbcTemplate提供的Connection,由用戶使用該Conncetion創建相關的CallableStatement;
● 預編譯語句設值回調:用於給預編譯語句相應參數設值;
PreparedStatementSetter:通過回調獲取JdbcTemplate提供的PreparedStatement,由用戶來對相應的預編譯語句相應參數設值;
BatchPreparedStatementSetter:;類似於PreparedStatementSetter,但用於批處理,需要指定批處理大小;
● 自定義功能回調:提供給用戶一個擴展點,用戶可以在指定類型的擴展點執行任何數量需要的操作;
ConnectionCallback:通過回調獲取JdbcTemplate提供的Connection,用戶可在該Connection執行任何數量的操作;
StatementCallback:通過回調獲取JdbcTemplate提供的Statement,用戶可以在該Statement執行任何數量的操作;
PreparedStatementCallback:通過回調獲取JdbcTemplate提供的PreparedStatement,用戶可以在該PreparedStatement執行任何數量的操作;
CallableStatementCallback:通過回調獲取JdbcTemplate提供的CallableStatement,用戶可以在該CallableStatement執行任何數量的操作;
● 結果集處理回調:通過回調處理ResultSet或將ResultSet轉換爲需要的形式;
RowMapper:用於將結果集每行數據轉換爲需要的類型,用戶需實現方法mapRow(ResultSet rs, int rowNum)來完成將每行數據轉換爲相應的類型。
RowCallbackHandler:用於處理ResultSet的每一行結果,用戶需實現方法processRow(ResultSet rs)來完成處理,在該回調方法中無需執行rs.next(),該操作由JdbcTemplate來執行,用戶只需按行獲取數據然後處理即可。
ResultSetExtractor:用於結果集數據提取,用戶需實現方法extractData(ResultSet rs)來處理結果集,用戶必須處理整個結果集;
- /**
- *
- * @author Chou
- * @since 2012-9-9
- * SpringJdbc並沒有像Hibernate那樣把AutoCommit設置爲false,
- * 所以沒有配置事務的情況下,默認是自動提交
- */
- public class JdbcTemplateDao extends JdbcDaoSupport{
- public void setDadasource(DataSource dataSource) {
- super.setDataSource(dataSource);
- }
- public void commonSql() {
- String insertSql = "insert into tab_item values(?,?,?)";
- String updateSql = "update tab_item set itemno = ?, itemname = ? where id = ?";
- String deleteSql = "delete tab_item where id = ?";
- Assert.isTrue(
- getJdbcTemplate().update(insertSql, new Object[]{4, "HP", "PT540"}) == 1, "插入失敗");
- Assert.isTrue(
- getJdbcTemplate().update(updateSql, new Object[]{"HP", "PT555", 4}) == 1, "修改失敗");
- Assert.isTrue(
- getJdbcTemplate().update(deleteSql, new Object[]{4}) == 1, "刪除失敗");
- }
- /**
- * 預編譯語句設值回調使用
- * 通過JdbcTemplate的int update(String sql, PreparedStatementSetter pss)執行預編譯sql
- */
- public void preparedStatementSql() {
- String sql = "insert into tab_item values(?,?,?)";
- int row = getJdbcTemplate().update(sql, new PreparedStatementSetter() {
- @Override
- public void setValues(PreparedStatement ps) throws SQLException {
- ps.setInt(1, 101);// JDBC佔位符集合的序號是從1開始的,而不是0
- ps.setObject(2, "Apple");
- ps.setString(3, "Ipad4");
- }
- });
- Assert.isTrue(row == 1, "插入失敗");
- // JdbcTemplate也提供一種更簡單的方式設值相應的佔位符位置的值
- sql = "delete from tab_item where id = ?";
- row = getJdbcTemplate().update(sql, new Object[] { 101 });
- Assert.isTrue(row == 1, "刪除失敗");
- }
- public void queryCallback() {
- String listSql = "select * from player";
- /**
- * RowMapper接口提供mapRow(ResultSet rs, int rowNum)
- * 方法將結果集的每一行轉換爲一個Map,當然可以轉換爲其他類,如表的對象化形式。
- */
- List<Map> result = getJdbcTemplate().query(listSql, new RowMapper<Map>() {
- @Override
- public Map mapRow(ResultSet rs, int rowNum) throws SQLException {
- System.out.println(rowNum);
- Map<Long,String> map = new HashMap<Long, String>();
- map.put(rs.getLong("id"), rs.getString("name"));
- return map;
- }
- });
- Iterator it = result.iterator();
- while (it.hasNext()) {
- Map<Long,String> map = (Map<Long, String>) it.next();
- System.out.println(map.values());
- }
- /**
- * RowCallbackHandler接口也提供方法processRow(ResultSet rs),
- * 能將結果集的行轉換爲需要的形式。
- */
- getJdbcTemplate().query(listSql, new RowCallbackHandler() {
- @Override
- public void processRow(ResultSet rs) throws SQLException {
- System.out.println("處理結果集");
- System.out.print("id:" + rs.getInt("id") + "***");
- System.out.println("name:" + rs.getString("name"));
- }
- });
- /**
- * ResultSetExtractor使用回調方法extractData(ResultSet rs)提供整個結果集,
- * 讓用戶決定如何處理該結果集
- */
- List list = getJdbcTemplate().query(listSql, new ResultSetExtractor<List>() {
- @Override
- public List extractData(ResultSet rs) throws SQLException,DataAccessException {
- List result = new ArrayList();
- while(rs.next()) {
- Map row = new HashMap();
- row.put(rs.getInt("id"), rs.getString("name"));
- result.add(row);
- System.out.println(row);
- }
- return result;
- }
- });
- }
- /**
- * JdbcTemplate提供更簡單的queryForXXX方法,來簡化開發:
- */
- private void queryForSimple() {
- //1.查詢一行數據並返回int型結果
- int countRs = getJdbcTemplate().queryForInt("select count(*) from player");
- System.out.println(countRs);
- //2. 查詢一行數據並將該行數據轉換爲Map返回
- Map map = getJdbcTemplate().queryForMap("select * from tab_item where id = ?", new Object[]{100});
- System.out.println(map.values());
- //3.查詢一行任何類型的數據,最後一個參數指定返回結果類型
- countRs = getJdbcTemplate().queryForObject("select count(*) from player", Integer.class);
- System.out.println(countRs);
- //4.查詢一批數據,默認將每行數據轉換爲Map
- List<Map<String, Object>> list = getJdbcTemplate().queryForList("select * from player");
- System.out.println(list.get(0).values());
- //5.只查詢一列數據列表,列類型是String類型,列名字是name
- List<String> names = getJdbcTemplate().queryForList("select itemname from tab_item where itemname=?", new Object[]{"雷蛇鼠標"}, String.class);
- System.out.println(names.size());
- //6.查詢一批數據,返回爲SqlRowSet,類似於ResultSet,但不再綁定到連接上
- SqlRowSet rs = getJdbcTemplate().queryForRowSet("select * from player");
- }
- /**
- * 調用建表,刪表語句
- * 數據庫不同,創建存儲過程的SQL也不同
- */
- public void createProcedure() {
- String createTableSql = "create memory table test" +
- "(id int GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, " +
- "name varchar(100))";
- String dropTableSql = "drop table test";
- String createHsqldbFunctionSql =
- "CREATE FUNCTION FUNCTION_TEST(str CHAR(100)) " +
- "returns INT begin atomic return length(str);end";
- getJdbcTemplate().update(createHsqldbFunctionSql);
- String createProcedureSql =
- "CREATE PROCEDURE PROCEDURE_TEST" +
- "(INOUT inOutName VARCHAR(100), OUT outId INT) " +
- "MODIFIES SQL DATA " +
- "BEGIN ATOMIC " +
- " insert into test(name) values (inOutName); " +
- " SET outId = IDENTITY(); " +
- " SET inOutName = 'Hello,' + inOutName; " +
- "END";
- getJdbcTemplate().update(createTableSql);
- getJdbcTemplate().execute(createProcedureSql);
- getJdbcTemplate().execute("DROP FUNCTION FUNCTION_TEST");
- getJdbcTemplate().execute("DROP PROCEDURE PROCEDURE_TEST");
- getJdbcTemplate().execute(dropTableSql);
- }
- /**
- * @return DriverManagerDataSource 返回數據源對象dataSource
- */
- public static DriverManagerDataSource getMyDataSource() {
- DriverManagerDataSource dataSource = new DriverManagerDataSource(url,
- username, password);
- dataSource.setDriverClassName(driver);
- return dataSource;
- }
- }
NamedParameterJdbcTemplate
NamedParameterJdbcTemplate類是基於JdbcTemplate類,並對它進行了封裝從而支持命名參數特性。NamedParameterJdbcTemplate主要提供以下三類方法: execute方法、 query及queryForXXX方法、update及batchUpdate方法。
- /**
- * @author Chou
- * @since 2012-9-9
- */
- public class NamedParameterJdbcTemplateDao extends NamedParameterJdbcDaoSupport{
- public void setDadasource(DataSource dataSource) {
- super.setDataSource(dataSource);
- }
- public void commonSql() {
- //可以使用DataSource或JdbcTemplate對象作爲構造器參數初始化
- namedParameterJdbcTemplate = new NamedParameterJdbcTemplate(getJdbcTemplate());
- String insertSql = "insert into tab_item values(:id, :itemno, :itemname)";
- String deleteSql = "delete from tab_item where id = :id";
- String selectSql = "select * from player where place = :place";
- //NamedParameterJdbcTemplate類爲命名參數設值有兩種方式:java.util.Map和SqlParameterSource
- Map<String, Object> paramMap = new HashMap<String, Object>();
- paramMap.put("id", 101);
- paramMap.put("itemno", "Menzu");
- paramMap.put("itemname", "MP4");
- int row = namedParameterJdbcTemplate.update(insertSql, paramMap);
- Assert.isTrue(row == 1, "插入失敗");
- /**
- * 可以使用SqlParameterSource實現作爲來實現爲命名參數設值,默認有MapSqlParameterSource
- * 和BeanPropertySqlParameterSource實現;MapSqlParameterSource實現非常簡單,
- * 只是封裝了java.util.Map;而BeanPropertySqlParameterSource封裝了一個JavaBean對象,
- * 通過JavaBean對象屬性來決定命名參數的值。
- * 可以看出BeanPropertySqlParameterSource使用能減少很多工作量,
- * 但命名參數必須和JavaBean屬性名稱相對應纔可以。
- */
- //Map<String, Object> paramMap2 = new HashMap<String, Object>();
- //paramMap2.put("id", 1);
- //SqlParameterSource paramSource = new MapSqlParameterSource(paramMap2);
- Item model = new Item();
- model.setId(101l);
- SqlParameterSource paramSource = new BeanPropertySqlParameterSource(model);
- row = namedParameterJdbcTemplate.update(deleteSql, paramSource);
- Assert.isTrue(row == 1, "刪除失敗");
- Map<String, Object> paramMap1 = new HashMap<String, Object>();
- paramMap1.put("place","PG ");
- namedParameterJdbcTemplate.query(selectSql, paramMap1, new RowCallbackHandler() {
- @Override
- public void processRow(ResultSet rs) throws SQLException {
- System.out.println(rs.getString("name"));
- }
- });
- }
- }
- public class Item {
- private Long id;
- private String itemno;
- private String itemname;
- //省略get和set方法
- }
SimpleJdbcTemplate
SimpleJdbcTemplate類也是基於JdbcTemplate類,但利用Java5+的可變參數列表和自動裝箱和拆箱從而獲取更簡潔的代碼。但是SimpleJdbcDaoSupport在Spring3.X中已經不推薦使用了。
- /**
- * @author Chou
- * @since 2012-9-9
- */
- public class SimpleJdbcTemplateDao extends SimpleJdbcDaoSupport{
- public void setDadasource(DataSource dataSource) {
- super.setDataSource(dataSource);
- }
- public void commonSql() {
- String insertSql = "update tab_item set itemno = :itemno where itemno = :itemno2";
- int rows = getSimpleJdbcTemplate().update(insertSql, "APPLE", "Apple");
- System.out.println(rows);
- }
- }
SimpleJdbc
Spring JDBC抽象框架提供SimpleJdbcInsert和SimpleJdbcCall類,這兩個類通過利用JDBC驅動提供的數據庫元數據來簡化JDBC操作。下面代碼演示SimpleJdbcInsert用法,SimpleJdbcCall用於調用存儲過程及自定義函數,可以參考博客:http://jinnianshilongnian.iteye.com/blog/1428149
- /**
- * @author Chou
- * @since 2012-9-9
- */
- @SuppressWarnings("deprecation")
- public class SimpleJdbcTemplateDao{
- private static SimpleJdbcInsert insert;
- public static void main(String[] args) {
- insert = new SimpleJdbcInsert(JdbcTemplateTest.getMyDataSource());
- simpleInsetId()
- System.out.println(insert.getInsertString());
- }
- public static void simpleInsetId() {
- insert.withTableName("tab_item");
- //主鍵是數據庫自動生成的情況下
- insert.setGeneratedKeyName("id");
- Map<String, Object> args = new HashMap<String, Object>();
- args.put("itemno", "SONY");
- args.put("itemname", "SONY");
- /**
- * executeAndReturnKey用於執行並獲取自動生成主鍵(注意是Number類型),
- * 必須首先通過setGeneratedKeyName設置主鍵然後才能獲取,如果想獲取復
- * 合主鍵請使用setGeneratedKeyNames描述主鍵然後通過executeReturningKeyHolder
- * 獲取複合主鍵KeyHolder對象;
- */
- Number id = insert.executeAndReturnKey(args);
- System.out.println(id);
- }
- }
SpringJdbc批量操作
- public class BatchExecuteDao extends JdbcDaoSupport{
- public void setDadasource(DataSource dataSource) {
- super.setDataSource(dataSource);
- }
- @SuppressWarnings("unchecked")
- public void batchBySimpleJdbcInsert() {
- SimpleJdbcInsert insert = new SimpleJdbcInsert(getJdbcTemplate());
- insert.withTableName("tab_item");
- Map<String, Object> valueMap = new HashMap<String, Object>();
- valueMap.put("id", 101);
- valueMap.put("itemno", "SONY");
- valueMap.put("itemname", "SONY");
- Map<String, Object> valueMap2 = new HashMap<String, Object>();
- valueMap2.put("id", 102);
- valueMap2.put("itemno", "SONY");
- valueMap2.put("itemname", "SONY");
- insert.executeBatch(new Map[] {valueMap, valueMap2});
- System.out.println(insert.getInsertString());
- }
- /**
- * 使用batchUpdate(String sql, List<Object[]> batchArgs)方法完成佔位符批處理,
- * 當然也支持命名參數批處理等
- */
- public void batchBySimpleJdbcTemplate() {
- SimpleJdbcTemplate simpleJdbcTemplate = new SimpleJdbcTemplate(getJdbcTemplate());
- String deleteSql = "delete tab_item where id = :id";
- List<Object[]> params = new ArrayList<Object[]>();
- params.add(new Object[]{101});
- params.add(new Object[]{102});
- params.add(new Object[]{103});
- params.add(new Object[]{104});
- simpleJdbcTemplate.batchUpdate(deleteSql, params);
- }
- public void batchByNamedParameterJdbcTemplate() {
- NamedParameterJdbcTemplate namedParameterJdbcTemplate = new NamedParameterJdbcTemplate(getJdbcTemplate());
- String updateSql = "update tab_item set itemname = :itemname where id = :id";
- Item model1 = new Item();
- Item model2 = new Item();
- Item model3 = new Item();
- Item model4 = new Item();
- model1.setId(101l);
- model2.setId(102l);
- model3.setId(103l);
- model4.setId(104l);
- model1.setItemname("I9100");
- model2.setItemname("I9101");
- model3.setItemname("I9102");
- model4.setItemname("I9103");
- SqlParameterSource[] params = SqlParameterSourceUtils.createBatch(new Object[] {model1, model2, model3, model4});
- namedParameterJdbcTemplate.batchUpdate(updateSql, params);
- }
- /**
- * 通過batchUpdate(String sql, final BatchPreparedStatementSetter pss)方法進行批處理,
- * 該方式使用預編譯語句,然後通過BatchPreparedStatementSetter實現進行設值(setValues)
- * 及指定批處理大小(getBatchSize)。
- */
- public void batchByJdbcTemplate() {
- String insertSql = "insert into tab_item values(?,?,?)";
- Object[] arg1 = {101, "SUMSUNG", "GAS1"};
- Object[] arg2 = {102, "SUMSUNG", "GAS2"};
- Object[] arg3 = {103, "SUMSUNG", "GAS3"};
- Object[] arg4 = {104, "SUMSUNG", "GAS4"};
- final List<Object[]> list = new ArrayList<Object[]>();
- list.add(arg1);
- list.add(arg2);
- list.add(arg3);
- list.add(arg4);
- int[] rows = getJdbcTemplate().batchUpdate(insertSql, new BatchPreparedStatementSetter() {
- @Override
- public void setValues(PreparedStatement ps, int i) throws SQLException {
- Object[] obj = list.get(i);
- ps.setInt(1, (Integer) obj[0]);
- ps.setString(2, (String) obj[1]);
- ps.setString(3, (String)obj[2]);
- }
- @Override
- public int getBatchSize() {//返回批量操作數最大值
- return list.size();
- }
- });
- System.out.println(getJdbcTemplate().getFetchSize());
- System.out.println(getJdbcTemplate().getQueryTimeout());
- for (int i = 0; i < rows.length; i++) {
- System.out.println(rows[i]);
- }
- Assert.isTrue(list.size() == getJdbcTemplate().queryForInt("select count(1) from tab_item where itemno = 'SUMSUNG'"), "批量更新失敗");
- }
- }
- ...
- <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
- <property name="locations">
- <list>
- <value>classpath:application.properties</value>
- </list>
- </property>
- </bean>
- <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
- <!-- Connection Info -->
- <property name="driverClassName" value="${db.driver.class}" />
- <property name="url" value="${db.url}" />
- <property name="username" value="${db.username}" />
- <property name="password" value="${db.password}" />
- <!-- Connection Pooling Info -->
- <property name="initialSize" value="${proxool.initialSize}" />
- <property name="maxActive" value="${proxool.maxActive}" />
- <property name="maxIdle" value="${proxool.maxIdle}" />
- <property name="minIdle" value="${proxool.minIdle}" />
- <property name="maxWait" value="500" />
- <property name="poolPreparedStatements" value="false" />
- </bean>
- <bean id="abstractDao" abstract="true">
- <property name="dataSource" ref="dataSource"/>
- </bean>
- <bean id="dao1" class="com.chou.jdbc.JdbcTemplateDao" parent="abstractDao"/>
- <bean id="dao2" class="com.chou.jdbc.NamedParameterJdbcTemplateDao" parent="abstractDao"/>
- <bean id="dao3" class="com.chou.jdbc.SimpleJdbcTemplateDao" parent="abstractDao"/>
- <bean id="dao4" class="com.chou.jdbc.BatchExecuteDao" parent="abstractDao"/>
- ...
- db.driver.class=oracle.jdbc.driver.OracleDriver
- db.url=jdbc:oracle:thin:@127.0.0.1:1521:orcl
- db.username=db_test
- db.password=db_test
- #連接池連接數初始值
- proxool.initialSize=2
- #連接池最大連接數量
- proxool.maxActive=10
- #連接池最大空閒值,釋放多餘的不用的連接,釋放到多少爲止
- proxool.maxIdle=5
- #連接池最小空閒值,當空閒連接數小於這個數的時候,連接池就會去申請一些連接以免高峯期來不及申請
- proxool.minIdle=1
Spring JDBC自身提供了以下DataSource實現:
- DriverManagerDataSource :簡單封裝了DriverManager獲取數據庫連接;通過DriverManager的getConnection方法獲取數據庫連接;
- SingleConnectionDataSource :內部封裝了一個連接,該連接使用後不會關閉,且不能在多線程環境中使用,一般用於測試;
- LazyConnectionDataSourceProxy :包裝一個DataSource,用於延遲獲取數據庫連接,只有在真正創建Statement等時才獲取連接,因此再說實際項目中最後使用該代理包裝原始DataSource從而使得只有在真正需要連接時纔去獲取。
Spring也能通過第三方提供的連接池實現主要有C3P0、Proxool、DBCP
DBCP沒有自動的去回收空閒連接的功能
C3P0有自動回收空閒連接功能,它實現了數據源和JNDI綁定,支持JDBC3規範和JDBC2的標準擴展。
DataSourceUtils:
Spring JDBC抽象框架內部都是通過它的getConnection(DataSource dataSource)方法獲取數據庫連接,releaseConnection(Connection con, DataSource dataSource) 用於釋放數據庫連接,DataSourceUtils用於支持Spring管理事務,只有使用DataSourceUtils獲取的連接才具有Spring管理事務。
SpringJdbc在插入數據時也可以獲取數據庫自動生成的主鍵,具體用法可以參考博客:http://jinnianshilongnian.iteye.com/blog/1428149