Spring3核心技術之JdbcTemplate

Spring3核心技術之JdbcTemplate

Spring對JDBC的支持
Spring通過抽象JDBC訪問並提供一致的API來簡化JDBC編程的工作量。我們只需要聲明SQL、調用合適的Spring JDBC框架API、處理結果集即可。事務由Spring管理,並將JDBC受查異常轉換爲Spring一致的非受查異常,從而簡化開發。

Java代碼
  1. ....
  2. Connection conn = null;
  3. PreparedStatement pstmt = null;
  4. try {
  5. conn = getConnection(); //1.獲取JDBC連接
  6. String sql = "select * from tableName"; //2.聲明SQL
  7. pstmt = conn.prepareStatement(sql); //3.預編譯SQL
  8. ResultSet rs = pstmt.executeQuery(); //4.執行SQL
  9. process(rs); //5.處理結果集
  10. closeResultSet(rs); //5.釋放結果集
  11. closeStatement(pstmt); //6.釋放Statement
  12. conn.commit(); //8.提交事務
  13. } catch (Exception e) {
  14. //9.處理異常並回滾事務
  15. conn.rollback();
  16. throw e;
  17. } finally {
  18. //10.釋放JDBC連接,防止JDBC連接不關閉造成的內存泄漏
  19. closeConnection(conn);
  20. }
  21. ....

以上代碼片段具有冗長、重複、容易忘記某一步驟從而導致出錯、顯示控制事務、顯示處理受檢查異常等等。
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還提供了一些強大的工具類,如DataSourceUtils來在必要的時候手工獲取數據庫連接等。

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)來處理結果集,用戶必須處理整個結果集;
Java代碼
  1. /**
  2. *
  3. * @author Chou
  4. * @since 2012-9-9
  5. * SpringJdbc並沒有像Hibernate那樣把AutoCommit設置爲false,
  6. * 所以沒有配置事務的情況下,默認是自動提交
  7. */
  8. public class JdbcTemplateDao extends JdbcDaoSupport{

  9. public void setDadasource(DataSource dataSource) {
  10. super.setDataSource(dataSource);
  11. }

  12. public void commonSql() {
  13. String insertSql = "insert into tab_item values(?,?,?)";
  14. String updateSql = "update tab_item set itemno = ?, itemname = ? where id = ?";
  15. String deleteSql = "delete tab_item where id = ?";

  16. Assert.isTrue(
  17. getJdbcTemplate().update(insertSql, new Object[]{4, "HP", "PT540"}) == 1, "插入失敗");
  18. Assert.isTrue(
  19. getJdbcTemplate().update(updateSql, new Object[]{"HP", "PT555", 4}) == 1, "修改失敗");
  20. Assert.isTrue(
  21. getJdbcTemplate().update(deleteSql, new Object[]{4}) == 1, "刪除失敗");
  22. }

  23. /**
  24. * 預編譯語句設值回調使用
  25. * 通過JdbcTemplate的int update(String sql, PreparedStatementSetter pss)執行預編譯sql
  26. */
  27. public void preparedStatementSql() {
  28. String sql = "insert into tab_item values(?,?,?)";
  29. int row = getJdbcTemplate().update(sql, new PreparedStatementSetter() {
  30. @Override
  31. public void setValues(PreparedStatement ps) throws SQLException {
  32. ps.setInt(1, 101);// JDBC佔位符集合的序號是從1開始的,而不是0
  33. ps.setObject(2, "Apple");
  34. ps.setString(3, "Ipad4");
  35. }
  36. });
  37. Assert.isTrue(row == 1, "插入失敗");

  38. // JdbcTemplate也提供一種更簡單的方式設值相應的佔位符位置的值
  39. sql = "delete from tab_item where id = ?";
  40. row = getJdbcTemplate().update(sql, new Object[] { 101 });
  41. Assert.isTrue(row == 1, "刪除失敗");
  42. }

  43. public void queryCallback() {
  44. String listSql = "select * from player";

  45. /**
  46. * RowMapper接口提供mapRow(ResultSet rs, int rowNum)
  47. * 方法將結果集的每一行轉換爲一個Map,當然可以轉換爲其他類,如表的對象化形式。
  48. */
  49. List<Map> result = getJdbcTemplate().query(listSql, new RowMapper<Map>() {
  50. @Override
  51. public Map mapRow(ResultSet rs, int rowNum) throws SQLException {
  52. System.out.println(rowNum);
  53. Map<Long,String> map = new HashMap<Long, String>();
  54. map.put(rs.getLong("id"), rs.getString("name"));
  55. return map;
  56. }
  57. });
  58. Iterator it = result.iterator();
  59. while (it.hasNext()) {
  60. Map<Long,String> map = (Map<Long, String>) it.next();
  61. System.out.println(map.values());
  62. }

  63. /**
  64. * RowCallbackHandler接口也提供方法processRow(ResultSet rs),
  65. * 能將結果集的行轉換爲需要的形式。
  66. */
  67. getJdbcTemplate().query(listSql, new RowCallbackHandler() {
  68. @Override
  69. public void processRow(ResultSet rs) throws SQLException {
  70. System.out.println("處理結果集");
  71. System.out.print("id:" + rs.getInt("id") + "***");
  72. System.out.println("name:" + rs.getString("name"));
  73. }
  74. });

  75. /**
  76. * ResultSetExtractor使用回調方法extractData(ResultSet rs)提供整個結果集,
  77. * 讓用戶決定如何處理該結果集
  78. */
  79. List list = getJdbcTemplate().query(listSql, new ResultSetExtractor<List>() {
  80. @Override
  81. public List extractData(ResultSet rs) throws SQLException,DataAccessException {
  82. List result = new ArrayList();
  83. while(rs.next()) {
  84. Map row = new HashMap();
  85. row.put(rs.getInt("id"), rs.getString("name"));
  86. result.add(row);
  87. System.out.println(row);
  88. }
  89. return result;
  90. }
  91. });
  92. }

  93. /**
  94. * JdbcTemplate提供更簡單的queryForXXX方法,來簡化開發:
  95. */
  96. private void queryForSimple() {
  97. //1.查詢一行數據並返回int型結果
  98. int countRs = getJdbcTemplate().queryForInt("select count(*) from player");
  99. System.out.println(countRs);

  100. //2. 查詢一行數據並將該行數據轉換爲Map返回
  101. Map map = getJdbcTemplate().queryForMap("select * from tab_item where id = ?", new Object[]{100});
  102. System.out.println(map.values());

  103. //3.查詢一行任何類型的數據,最後一個參數指定返回結果類型
  104. countRs = getJdbcTemplate().queryForObject("select count(*) from player", Integer.class);
  105. System.out.println(countRs);

  106. //4.查詢一批數據,默認將每行數據轉換爲Map
  107. List<Map<String, Object>> list = getJdbcTemplate().queryForList("select * from player");
  108. System.out.println(list.get(0).values());

  109. //5.只查詢一列數據列表,列類型是String類型,列名字是name
  110. List<String> names = getJdbcTemplate().queryForList("select itemname from tab_item where itemname=?", new Object[]{"雷蛇鼠標"}, String.class);
  111. System.out.println(names.size());

  112. //6.查詢一批數據,返回爲SqlRowSet,類似於ResultSet,但不再綁定到連接上
  113. SqlRowSet rs = getJdbcTemplate().queryForRowSet("select * from player");
  114. }

  115. /**
  116. * 調用建表,刪表語句
  117. * 數據庫不同,創建存儲過程的SQL也不同
  118. */
  119. public void createProcedure() {
  120. String createTableSql = "create memory table test" +
  121. "(id int GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, " +
  122. "name varchar(100))";

  123. String dropTableSql = "drop table test";

  124. String createHsqldbFunctionSql =
  125. "CREATE FUNCTION FUNCTION_TEST(str CHAR(100)) " +
  126. "returns INT begin atomic return length(str);end";
  127. getJdbcTemplate().update(createHsqldbFunctionSql);

  128. String createProcedureSql =
  129. "CREATE PROCEDURE PROCEDURE_TEST" +
  130. "(INOUT inOutName VARCHAR(100), OUT outId INT) " +
  131. "MODIFIES SQL DATA " +
  132. "BEGIN ATOMIC " +
  133. " insert into test(name) values (inOutName); " +
  134. " SET outId = IDENTITY(); " +
  135. " SET inOutName = 'Hello,' + inOutName; " +
  136. "END";

  137. getJdbcTemplate().update(createTableSql);
  138. getJdbcTemplate().execute(createProcedureSql);

  139. getJdbcTemplate().execute("DROP FUNCTION FUNCTION_TEST");
  140. getJdbcTemplate().execute("DROP PROCEDURE PROCEDURE_TEST");

  141. getJdbcTemplate().execute(dropTableSql);
  142. }
  143. /**
  144. * @return DriverManagerDataSource 返回數據源對象dataSource
  145. */
  146. public static DriverManagerDataSource getMyDataSource() {
  147. DriverManagerDataSource dataSource = new DriverManagerDataSource(url,
  148. username, password);
  149. dataSource.setDriverClassName(driver);
  150. return dataSource;
  151. }
  152. }

NamedParameterJdbcTemplate
NamedParameterJdbcTemplate類是基於JdbcTemplate類,並對它進行了封裝從而支持命名參數特性。NamedParameterJdbcTemplate主要提供以下三類方法: execute方法、 query及queryForXXX方法、update及batchUpdate方法。

Java代碼
  1. /**
  2. * @author Chou
  3. * @since 2012-9-9
  4. */
  5. public class NamedParameterJdbcTemplateDao extends NamedParameterJdbcDaoSupport{

  6. public void setDadasource(DataSource dataSource) {
  7. super.setDataSource(dataSource);
  8. }

  9. public void commonSql() {
  10. //可以使用DataSource或JdbcTemplate對象作爲構造器參數初始化
  11. namedParameterJdbcTemplate = new NamedParameterJdbcTemplate(getJdbcTemplate());
  12. String insertSql = "insert into tab_item values(:id, :itemno, :itemname)";
  13. String deleteSql = "delete from tab_item where id = :id";
  14. String selectSql = "select * from player where place = :place";

  15. //NamedParameterJdbcTemplate類爲命名參數設值有兩種方式:java.util.Map和SqlParameterSource
  16. Map<String, Object> paramMap = new HashMap<String, Object>();
  17. paramMap.put("id", 101);
  18. paramMap.put("itemno", "Menzu");
  19. paramMap.put("itemname", "MP4");
  20. int row = namedParameterJdbcTemplate.update(insertSql, paramMap);
  21. Assert.isTrue(row == 1, "插入失敗");

  22. /**
  23. * 可以使用SqlParameterSource實現作爲來實現爲命名參數設值,默認有MapSqlParameterSource
  24. * 和BeanPropertySqlParameterSource實現;MapSqlParameterSource實現非常簡單,
  25. * 只是封裝了java.util.Map;而BeanPropertySqlParameterSource封裝了一個JavaBean對象,
  26. * 通過JavaBean對象屬性來決定命名參數的值。
  27. * 可以看出BeanPropertySqlParameterSource使用能減少很多工作量,
  28. * 但命名參數必須和JavaBean屬性名稱相對應纔可以。
  29. */
  30. //Map<String, Object> paramMap2 = new HashMap<String, Object>();
  31. //paramMap2.put("id", 1);
  32. //SqlParameterSource paramSource = new MapSqlParameterSource(paramMap2);

  33. Item model = new Item();
  34. model.setId(101l);
  35. SqlParameterSource paramSource = new BeanPropertySqlParameterSource(model);

  36. row = namedParameterJdbcTemplate.update(deleteSql, paramSource);
  37. Assert.isTrue(row == 1, "刪除失敗");

  38. Map<String, Object> paramMap1 = new HashMap<String, Object>();
  39. paramMap1.put("place","PG ");
  40. namedParameterJdbcTemplate.query(selectSql, paramMap1, new RowCallbackHandler() {
  41. @Override
  42. public void processRow(ResultSet rs) throws SQLException {
  43. System.out.println(rs.getString("name"));
  44. }
  45. });
  46. }
  47. }

  48. public class Item {
  49. private Long id;
  50. private String itemno;
  51. private String itemname;

  52. //省略get和set方法
  53. }

SimpleJdbcTemplate
SimpleJdbcTemplate類也是基於JdbcTemplate類,但利用Java5+的可變參數列表和自動裝箱和拆箱從而獲取更簡潔的代碼。但是SimpleJdbcDaoSupport在Spring3.X中已經不推薦使用了。

Java代碼
  1. /**
  2. * @author Chou
  3. * @since 2012-9-9
  4. */
  5. public class SimpleJdbcTemplateDao extends SimpleJdbcDaoSupport{

  6. public void setDadasource(DataSource dataSource) {
  7. super.setDataSource(dataSource);
  8. }

  9. public void commonSql() {
  10. String insertSql = "update tab_item set itemno = :itemno where itemno = :itemno2";
  11. int rows = getSimpleJdbcTemplate().update(insertSql, "APPLE", "Apple");
  12. System.out.println(rows);
  13. }
  14. }

SimpleJdbc
Spring JDBC抽象框架提供SimpleJdbcInsert和SimpleJdbcCall類,這兩個類通過利用JDBC驅動提供的數據庫元數據來簡化JDBC操作。下面代碼演示SimpleJdbcInsert用法,SimpleJdbcCall用於調用存儲過程及自定義函數,可以參考博客:
http://jinnianshilongnian.iteye.com/blog/1428149

Java代碼
  1. /**
  2. * @author Chou
  3. * @since 2012-9-9
  4. */
  5. @SuppressWarnings("deprecation")
  6. public class SimpleJdbcTemplateDao{

  7. private static SimpleJdbcInsert insert;

  8. public static void main(String[] args) {
  9. insert = new SimpleJdbcInsert(JdbcTemplateTest.getMyDataSource());
  10. simpleInsetId()
  11. System.out.println(insert.getInsertString());
  12. }

  13. public static void simpleInsetId() {
  14. insert.withTableName("tab_item");
  15. //主鍵是數據庫自動生成的情況下
  16. insert.setGeneratedKeyName("id");

  17. Map<String, Object> args = new HashMap<String, Object>();
  18. args.put("itemno", "SONY");
  19. args.put("itemname", "SONY");

  20. /**
  21. * executeAndReturnKey用於執行並獲取自動生成主鍵(注意是Number類型),
  22. * 必須首先通過setGeneratedKeyName設置主鍵然後才能獲取,如果想獲取復
  23. * 合主鍵請使用setGeneratedKeyNames描述主鍵然後通過executeReturningKeyHolder
  24. * 獲取複合主鍵KeyHolder對象;
  25. */
  26. Number id = insert.executeAndReturnKey(args);
  27. System.out.println(id);
  28. }
  29. }


SpringJdbc批量操作
Java代碼
  1. public class BatchExecuteDao extends JdbcDaoSupport{

  2. public void setDadasource(DataSource dataSource) {
  3. super.setDataSource(dataSource);
  4. }

  5. @SuppressWarnings("unchecked")
  6. public void batchBySimpleJdbcInsert() {
  7. SimpleJdbcInsert insert = new SimpleJdbcInsert(getJdbcTemplate());
  8. insert.withTableName("tab_item");
  9. Map<String, Object> valueMap = new HashMap<String, Object>();
  10. valueMap.put("id", 101);
  11. valueMap.put("itemno", "SONY");
  12. valueMap.put("itemname", "SONY");
  13. Map<String, Object> valueMap2 = new HashMap<String, Object>();
  14. valueMap2.put("id", 102);
  15. valueMap2.put("itemno", "SONY");
  16. valueMap2.put("itemname", "SONY");
  17. insert.executeBatch(new Map[] {valueMap, valueMap2});
  18. System.out.println(insert.getInsertString());
  19. }

  20. /**
  21. * 使用batchUpdate(String sql, List<Object[]> batchArgs)方法完成佔位符批處理,
  22. * 當然也支持命名參數批處理等
  23. */
  24. public void batchBySimpleJdbcTemplate() {
  25. SimpleJdbcTemplate simpleJdbcTemplate = new SimpleJdbcTemplate(getJdbcTemplate());
  26. String deleteSql = "delete tab_item where id = :id";
  27. List<Object[]> params = new ArrayList<Object[]>();
  28. params.add(new Object[]{101});
  29. params.add(new Object[]{102});
  30. params.add(new Object[]{103});
  31. params.add(new Object[]{104});
  32. simpleJdbcTemplate.batchUpdate(deleteSql, params);

  33. }

  34. public void batchByNamedParameterJdbcTemplate() {
  35. NamedParameterJdbcTemplate namedParameterJdbcTemplate = new NamedParameterJdbcTemplate(getJdbcTemplate());
  36. String updateSql = "update tab_item set itemname = :itemname where id = :id";
  37. Item model1 = new Item();
  38. Item model2 = new Item();
  39. Item model3 = new Item();
  40. Item model4 = new Item();
  41. model1.setId(101l);
  42. model2.setId(102l);
  43. model3.setId(103l);
  44. model4.setId(104l);

  45. model1.setItemname("I9100");
  46. model2.setItemname("I9101");
  47. model3.setItemname("I9102");
  48. model4.setItemname("I9103");

  49. SqlParameterSource[] params = SqlParameterSourceUtils.createBatch(new Object[] {model1, model2, model3, model4});
  50. namedParameterJdbcTemplate.batchUpdate(updateSql, params);

  51. }

  52. /**
  53. * 通過batchUpdate(String sql, final BatchPreparedStatementSetter pss)方法進行批處理,
  54. * 該方式使用預編譯語句,然後通過BatchPreparedStatementSetter實現進行設值(setValues)
  55. * 及指定批處理大小(getBatchSize)。
  56. */
  57. public void batchByJdbcTemplate() {
  58. String insertSql = "insert into tab_item values(?,?,?)";
  59. Object[] arg1 = {101, "SUMSUNG", "GAS1"};
  60. Object[] arg2 = {102, "SUMSUNG", "GAS2"};
  61. Object[] arg3 = {103, "SUMSUNG", "GAS3"};
  62. Object[] arg4 = {104, "SUMSUNG", "GAS4"};
  63. final List<Object[]> list = new ArrayList<Object[]>();
  64. list.add(arg1);
  65. list.add(arg2);
  66. list.add(arg3);
  67. list.add(arg4);

  68. int[] rows = getJdbcTemplate().batchUpdate(insertSql, new BatchPreparedStatementSetter() {

  69. @Override
  70. public void setValues(PreparedStatement ps, int i) throws SQLException {
  71. Object[] obj = list.get(i);
  72. ps.setInt(1, (Integer) obj[0]);
  73. ps.setString(2, (String) obj[1]);
  74. ps.setString(3, (String)obj[2]);
  75. }

  76. @Override
  77. public int getBatchSize() {//返回批量操作數最大值
  78. return list.size();
  79. }
  80. });
  81. System.out.println(getJdbcTemplate().getFetchSize());
  82. System.out.println(getJdbcTemplate().getQueryTimeout());
  83. for (int i = 0; i < rows.length; i++) {
  84. System.out.println(rows[i]);
  85. }

  86. Assert.isTrue(list.size() == getJdbcTemplate().queryForInt("select count(1) from tab_item where itemno = 'SUMSUNG'"), "批量更新失敗");
  87. }
  88. }

Xml代碼
  1. ...
  2. <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
  3. <property name="locations">
  4. <list>
  5. <value>classpath:application.properties</value>
  6. </list>
  7. </property>
  8. </bean>

  9. <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
  10. <!-- Connection Info -->
  11. <property name="driverClassName" value="${db.driver.class}" />
  12. <property name="url" value="${db.url}" />
  13. <property name="username" value="${db.username}" />
  14. <property name="password" value="${db.password}" />

  15. <!-- Connection Pooling Info -->
  16. <property name="initialSize" value="${proxool.initialSize}" />
  17. <property name="maxActive" value="${proxool.maxActive}" />
  18. <property name="maxIdle" value="${proxool.maxIdle}" />
  19. <property name="minIdle" value="${proxool.minIdle}" />
  20. <property name="maxWait" value="500" />
  21. <property name="poolPreparedStatements" value="false" />
  22. </bean>

  23. <bean id="abstractDao" abstract="true">
  24. <property name="dataSource" ref="dataSource"/>
  25. </bean>

  26. <bean id="dao1" class="com.chou.jdbc.JdbcTemplateDao" parent="abstractDao"/>
  27. <bean id="dao2" class="com.chou.jdbc.NamedParameterJdbcTemplateDao" parent="abstractDao"/>
  28. <bean id="dao3" class="com.chou.jdbc.SimpleJdbcTemplateDao" parent="abstractDao"/>
  29. <bean id="dao4" class="com.chou.jdbc.BatchExecuteDao" parent="abstractDao"/>
  30. ...

Java代碼
  1. db.driver.class=oracle.jdbc.driver.OracleDriver
  2. db.url=jdbc:oracle:thin:@127.0.0.1:1521:orcl
  3. db.username=db_test
  4. db.password=db_test

  5. #連接池連接數初始值
  6. proxool.initialSize=2

  7. #連接池最大連接數量
  8. proxool.maxActive=10

  9. #連接池最大空閒值,釋放多餘的不用的連接,釋放到多少爲止
  10. proxool.maxIdle=5

  11. #連接池最小空閒值,當空閒連接數小於這個數的時候,連接池就會去申請一些連接以免高峯期來不及申請
  12. 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
發佈了93 篇原創文章 · 獲贊 8 · 訪問量 23萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章