<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                # 【第七章】 對JDBC的支持 之 7.3 關系數據庫操作對象化 ——跟我學spring3 ### 7.3.1? 概述 所謂**關系數據庫對象化其實就是用面向對象方式表示關系數據庫操作,從而可以復用。** Spring JDBC框架將數據庫操作封裝為一個RdbmsOperation,該對象是線程安全的、可復用的對象,是所有數據庫對象的父類。而SqlOperation繼承了RdbmsOperation,代表了數據庫SQL操作,如select、update、call等,如圖7-4所示。 ![](https://box.kancloud.cn/2016-05-13_5735471f7851e.JPG) 圖7-4 關系數據庫操作對象化支持類 數據庫操作對象化只要有以下幾種類型,所以類型是線程安全及可復用的: * **查詢:**將數據庫操作select封裝為對象,查詢操作的基類是SqlQuery,所有查詢都可以使用該類表示,Spring JDBC還提供了一些更容易使用的MappingSqlQueryWithParameters和MappingSqlQuery用于將結果集映射為Java對象,查詢對象類還提供了兩個擴展UpdatableSqlQuery和SqlFunction; * **更新:**即增刪改操作,將數據庫操作insert 、update、delete封裝為對象,增刪改基類是SqlUpdate,當然還提供了BatchSqlUpdate用于批處理; * **存儲過程及函數:**將存儲過程及函數調用封裝為對象,基類是SqlCall類,提供了StoredProcedure實現。 ### 7.3.2? 查詢 **1)SqlQuery:**需要覆蓋如下方法來定義一個RowMapper,其中parameters參數表示命名參數或占位符參數值列表,而context是由用戶傳入的上下文數據。 ``` RowMapper<T> newRowMapper(Object[] parameters, Map context) ``` SqlQuery提供兩類方法: * execute及executeByNamedParam方法:用于查詢多行數據,其中executeByNamedParam用于支持命名參數綁定參數; * findObject及findObjectByNamedParam方法:用于查詢單行數據,其中findObjectByNamedParam用于支持命名參數綁定。 演示一下SqlQuery如何使用: ``` @Test public void testSqlQuery() { SqlQuery query = new UserModelSqlQuery(jdbcTemplate); List<UserModel> result = query.execute("name5"); Assert.assertEquals(0, result.size()); } ``` 從測試代碼可以SqlQuery使用非常簡單,創建SqlQuery實現對象,然后調用相應的方法即可,接下來看一下SqlQuery實現: ``` package cn.javass.spring.chapter7; //省略import public class UserModelSqlQuery extends SqlQuery<UserModel> { public UserModelSqlQuery(JdbcTemplate jdbcTemplate) { //super.setDataSource(jdbcTemplate.getDataSource()); super.setJdbcTemplate(jdbcTemplate); super.setSql("select * from test where name=?"); super.declareParameter(new SqlParameter(Types.VARCHAR)); compile(); } @Override protected RowMapper<UserModel> newRowMapper(Object[] parameters, Map context) { return new UserRowMapper(); } } ``` 從測試代碼可以看出,具體步驟如下: 一、setJdbcTemplate/ setDataSource:首先設置數據源或JdbcTemplate; 二、setSql("select * from test where name=?"):定義sql語句,所以定義的sql語句都將被編譯為PreparedStatement; 三、declareParameter(new SqlParameter(Types.VARCHAR)):對PreparedStatement參數描述,使用SqlParameter來描述參數類型,支持命名參數、占位符描述; 對于命名參數可以使用如new SqlParameter("name", Types.VARCHAR)描述;注意占位符參數描述必須按占位符參數列表的順序進行描述; 四、編譯:可選,當執行相應查詢方法時會自動編譯,用于將sql編譯為PreparedStatement,對于編譯的SqlQuery不能再對參數進行描述了。 五、以上步驟是不可變的,必須按順序執行。 **2)MappingSqlQuery:**用于簡化SqlQuery中RowMapper創建,可以直接在實現mapRow(ResultSet rs, int rowNum)來將行數據映射為需要的形式; MappingSqlQuery所有查詢方法完全繼承于SqlQuery。 演示一下MappingSqlQuery如何使用: ``` @Test public void testMappingSqlQuery() { jdbcTemplate.update("insert into test(name) values('name5')"); SqlQuery<UserModel> query = new UserModelMappingSqlQuery(jdbcTemplate); Map<String, Object> paramMap = new HashMap<String, Object>(); paramMap.put("name", "name5"); UserModel result = query.findObjectByNamedParam(paramMap); Assert.assertNotNull(result); } ``` MappingSqlQuery使用和SqlQuery完全一樣,創建MappingSqlQuery實現對象,然后調用相應的方法即可,接下來看一下MappingSqlQuery實現,findObjectByNamedParam方法用于執行命名參數查詢: ``` package cn.javass.spring.chapter7; //省略import public class UserModelMappingSqlQuery extends MappingSqlQuery<UserModel> { public UserModelMappingSqlQuery(JdbcTemplate jdbcTemplate) { super.setDataSource(jdbcTemplate.getDataSource()); super.setSql("select * from test where name=:name"); super.declareParameter(new SqlParameter("name", Types.VARCHAR)); compile(); } @Override protected UserModel mapRow(ResultSet rs, int rowNum) throws SQLException { UserModel model = new UserModel(); model.setId(rs.getInt("id")); model.setMyName(rs.getString("name")); return model; } } ``` 和SqlQuery唯一不同的是使用mapRow來講每行數據轉換為需要的形式,其他地方完全一樣。 1)??**UpdatableSqlQuery:**提供可更新結果集查詢支持,子類實現updateRow(ResultSet rs, int rowNum, Map context)對結果集進行更新。 2)??**GenericSqlQuery:**提供setRowMapperClass(Class rowMapperClass)方法用于指定RowMapper實現,在此就不演示了。具體請參考testGenericSqlQuery()方法。 3)??**SqlFunction:**SQL“函數”包裝器,用于支持那些返回單行結果集的查詢。該類主要用于返回單行單列結果集。 ``` @Test public void testSqlFunction() { jdbcTemplate.update("insert into test(name) values('name5')"); String countSql = "select count(*) from test"; SqlFunction<Integer> sqlFunction1 = new SqlFunction<Integer>(jdbcTemplate.getDataSource(), countSql); Assert.assertEquals(1, sqlFunction1.run()); String selectSql = "select name from test where name=?"; SqlFunction<String> sqlFunction2 = new SqlFunction<String>(jdbcTemplate.getDataSource(), selectSql); sqlFunction2.declareParameter(new SqlParameter(Types.VARCHAR)); String name = (String) sqlFunction2.runGeneric(new Object[] {"name5"}); Assert.assertEquals("name5", name); } ``` 如代碼所示,SqlFunction初始化時需要DataSource和相應的sql語句,如果有參數需要使用declareParameter對參數類型進行描述;run方法默認返回int型,當然也可以使用runGeneric返回其他類型,如String等。 ### 7.3.3? 更新 SqlUpdate類用于支持數據庫更新操作,即增刪改(insert、delete、update)操作,該方法類似于SqlQuery,只是職責不一樣。 SqlUpdate提供了update及updateByNamedParam方法用于數據庫更新操作,其中updateByNamedParam用于命名參數類型更新。 演示一下SqlUpdate如何使用: ``` package cn.javass.spring.chapter7; //省略import public class InsertUserModel extends SqlUpdate { public InsertUserModel(JdbcTemplate jdbcTemplate) { super.setJdbcTemplate(jdbcTemplate); super.setSql("insert into test(name) values(?)"); super.declareParameter(new SqlParameter(Types.VARCHAR)); compile(); } } ``` ``` @Test public void testSqlUpdate() { SqlUpdate insert = new InsertUserModel(jdbcTemplate); insert.update("name5"); String updateSql = "update test set name=? where name=?"; SqlUpdate update = new SqlUpdate(jdbcTemplate.getDataSource(), updateSql, new int[]{Types.VARCHAR, Types.VARCHAR}); update.update("name6", "name5"); String deleteSql = "delete from test where name=:name"; SqlUpdate delete = new SqlUpdate(jdbcTemplate.getDataSource(), deleteSql, new int[]{Types.VARCHAR}); Map<String, Object> paramMap = new HashMap<String, Object>(); paramMap.put("name", "name5"); delete.updateByNamedParam(paramMap); } ``` InsertUserModel類實現類似于SqlQuery實現,用于執行數據庫插入操作,SqlUpdate還提供一種更簡潔的構造器SqlUpdate(DataSource ds, String sql, int[] types),其中types用于指定占位符或命名參數類型;SqlUpdate還支持命名參數,使用updateByNamedParam方法來進行命名參數操作。 ### 7.3.4? 存儲過程及函數 StoredProcedure用于支持存儲過程及函數,該類的使用同樣類似于SqlQuery。 StoredProcedure提供execute方法用于執行存儲過程及函數。 **一、StoredProcedure如何調用自定義函數:** ``` @Test public void testStoredProcedure1() { StoredProcedure lengthFunction = new HsqldbLengthFunction(jdbcTemplate); Map<String,Object> outValues = lengthFunction.execute("test"); Assert.assertEquals(4, outValues.get("result")); } ``` StoredProcedure使用非常簡單,定義StoredProcedure實現HsqldbLengthFunction,并調用execute方法執行即可,接下來看一下HsqldbLengthFunction實現: ``` package cn.javass.spring.chapter7; //省略import public class HsqldbLengthFunction extends StoredProcedure { public HsqldbLengthFunction(JdbcTemplate jdbcTemplate) { super.setJdbcTemplate(jdbcTemplate); super.setSql("FUNCTION_TEST"); super.declareParameter( new SqlReturnResultSet("result", new ResultSetExtractor<Integer>() { @Override public Integer extractData(ResultSet rs) throws SQLException, DataAccessException { while(rs.next()) { return rs.getInt(1); } return 0; } })); super.declareParameter(new SqlParameter("str", Types.VARCHAR)); compile(); } } ``` StoredProcedure自定義函數使用類似于SqlQuery,首先設置數據源或JdbcTemplate對象,其次定義自定義函數,然后使用declareParameter進行參數描述,最后調用compile(可選)編譯自定義函數。 接下來看一下mysql自定義函數如何使用: ``` @Test public void testStoredProcedure2() { JdbcTemplate mysqlJdbcTemplate = new JdbcTemplate(getMysqlDataSource()); String createFunctionSql = "CREATE FUNCTION FUNCTION_TEST(str VARCHAR(100)) " + "returns INT return LENGTH(str)"; String dropFunctionSql = "DROP FUNCTION IF EXISTS FUNCTION_TEST"; mysqlJdbcTemplate.update(dropFunctionSql); mysqlJdbcTemplate.update(createFunctionSql); StoredProcedure lengthFunction = new MysqlLengthFunction(mysqlJdbcTemplate); Map<String,Object> outValues = lengthFunction.execute("test"); Assert.assertEquals(4, outValues.get("result")); } ``` MysqlLengthFunction自定義函數使用與HsqldbLengthFunction使用完全一樣,只是內部實現稍有差別: ``` package cn.javass.spring.chapter7; //省略import public class MysqlLengthFunction extends StoredProcedure { public MysqlLengthFunction(JdbcTemplate jdbcTemplate) { super.setJdbcTemplate(jdbcTemplate); super.setSql("FUNCTION_TEST"); super.setFunction(true); super.declareParameter(new SqlOutParameter("result", Types.INTEGER)); super.declareParameter(new SqlParameter("str", Types.VARCHAR)); compile(); } } ``` MysqlLengthFunction與HsqldbLengthFunction實現不同的地方有兩點: * **setFunction(true):**表示是自定義函數調用,即編譯后的sql為{?= call …}形式;如果使用hsqldb不能設置為true,因為在hsqldb中{?= call …}和{call …}含義一樣; * **declareParameter(new SqlOutParameter("result", Types.INTEGER))**:將自定義函數返回值類型直接描述為Types.INTEGER;SqlOutParameter必須指定name,而不用使用SqlReturnResultSet首先獲取結果集,然后再從結果集獲取返回值,這是mysql與hsqldb的區別; **一、StoredProcedure如何調用存儲過程:** ``` @Test public void testStoredProcedure3() { StoredProcedure procedure = new HsqldbTestProcedure(jdbcTemplate); Map<String,Object> outValues = procedure.execute("test"); Assert.assertEquals(0, outValues.get("outId")); Assert.assertEquals("Hello,test", outValues.get("inOutName")); } ``` StoredProcedure存儲過程實現HsqldbTestProcedure調用與HsqldbLengthFunction調用完全一樣,不同的是在實現時,參數描述稍有不同: ``` package cn.javass.spring.chapter7; //省略import public class HsqldbTestProcedure extends StoredProcedure { public HsqldbTestProcedure(JdbcTemplate jdbcTemplate) { super.setJdbcTemplate(jdbcTemplate); super.setSql("PROCEDURE_TEST"); super.declareParameter(new SqlInOutParameter("inOutName", Types.VARCHAR)); super.declareParameter(new SqlOutParameter("outId", Types.INTEGER)); compile(); } } ``` * **declareParameter:**使用SqlInOutParameter描述INOUT類型參數,使用SqlOutParameter描述OUT類型參數,必須按順序定義,不能顛倒。 原創內容,轉載請注明出處【[http://sishuok.com/forum/blogPost/list/0/2491.html](http://sishuok.com/forum/blogPost/list/0/2491.html#7206)】
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看