第四章. 征服資料庫
--------------------------------------------------------------------------------
31. Spring 把資料通路流程中的固定部分和可變部分分開,分别映射成兩截然不同的類,模闆(Template)和回調(Callback),模闆管事物控制、資源管理以及異常處理;回調實作特定于應用的部分--建立 statement、綁定參數、以及整理結果集。模闆方法模式的優秀應用(P123)
32. JdbcTemplate template = new JdbcTemplate(myDataSource); 構造。 所有 Spring Dao 模闆類是線程安全的,可以為每一個 DAO 配置一個 JdbcTemplate 屬性,也可以讓 DAO 類繼承 JdbcDaoSupport,然後在 DAO 類中用 getJdbcTemplate() 擷取到 JdbcTemplate 進行資料庫操作。書中的做法是給每個 Dao 加一個 JdbcTemplate 屬性,記錄的日志略有不同,實際中注意(P127)
33. JdbcTemplate 的 execute() 方法不可帶 sql 參數,即不存在 execute(String sql, Object[] params) 方法,而 update 才有 update(String sql, Object[] params) 方法可以,還能指定每一字段的類型(通過第三個參數 int[] argTypes),保證了類型安全,130頁說 JdbcTemplate 提供了 execute(String sql, Object[] params) 是錯誤的。(P130)
34. JdbcTemplate 類建立了 PreparedStatementCreator(createPreparedStatementCreator(Connection conn)) 和 PreparedStatementSetter(setValues(PreparedStatement ps)), 批量更新時需要建立自己的 BatchPreparedStatementCreator 類:
BatchPreparedStatementSetter setter = new BatchPreparedStatementSetter(){
public int getBatchSize(){ return persons.size();}
public void setValues(PreparedStatement ps, int index) throws SQLException{
Person person = (Person) persons.get(index);
ps.setInt(0,person.getId().intValue());
......
}
};
getJdbcTemplate().batchUpdate(sql,setter);
BatchPreparedStatementSetter setter = new BatchPreparedStatementSetter(){
public int getBatchSize(){ return persons.size();}
public void setValues(PreparedStatement ps, int index) throws SQLException{
Person person = (Person) persons.get(index);
ps.setInt(0,person.getId().intValue());
......
}
};
getJdbcTemplate().batchUpdate(sql,setter);
把傳入的List<Person>批量的進行資料庫相應操作(P131)
35. 用JdbcTemplate讀資料,可以用 JdbcTemplate.query(sql,params, rowCallbackHandler), 實作 RowCallbackHandler的 processRow(ResultSet rs) 組裝查詢到的一個對象。實作自己的 RowMapper把 ResultSet 中一條記錄映射成一個對象,用JdbcTemplate.query(sql, params, new MyRowMapper())能夠傳回查詢整理後的對象清單,書中 133 頁的帶 RowMapperResultReader的query方法已經不存在了,在 Spring 2.x 中連 RowMapperResultReader 這個類也沒啦,敬請關注 RowMapper。由此可見,即使是隻傳回一條記錄的查詢也可用帶 RowMapper的query方法,隻需傳回第一條記錄就行。(P132)
36. JdbcTemplate的 queryForXXX可更快捷傳回簡單的查詢值,如一個 count, 隻傳回一條記錄的一個字段的值。書上沒說這個,看 JdbcTemplate 代碼的方法發現的。
37. JdbcTemplate 調用存儲過程: jdbcTemplate.execute("{ARCHIVE_STUDENTS}", new CallableStatementCallback(){.....}); 看清了,就是要實作自己的 CallableStatementCallback的一個方法(P134)
public Object doInCallableStatement(CallableStatement cs){
cs.execute();
return null;
}
public Object doInCallableStatement(CallableStatement cs){
cs.execute();
return null;
}
38. 可以不使用 JdbcTemplate, 而擴充 SqlUpdate 和 MappingSqlQuery 把操作建立成對象,這種做法可以可以讓你的代碼幾乎不和 JDBC API 進行互動,不過我還是覺得用 JdbcTemplate 通俗易懂。擴充 DataFieldMaxValueIncrementer 取得自增鍵值,有三個方法 nextIntValue()、nextLongValue()、nextStringValue(),根據實際資料庫可以用不同的實作,如 Oracle、PostgreSQL、MySQL 和 Hypersonic 等資料庫的序列機制的實作或自己寫的實作。
39. Spring 隻需提供 ORM 架構的整合點,以及一些附加的服務:整合事務處理、異常處理、線程安全,輕量級模闆、便利的支援類、資源管理。Spring 整合 Hibernate 的關鍵在于對 LocalSessionFactoryBean 的配置,不再需要 hibernate.cfg.xml(或 hibernate.properties) 了。可用 LocalSessionFactoryBean 的 mappingDirectoryLocations 屬性加載某一路徑下的所有 *.hbm.xml 檔案。最後留意 HibernateTemplate(它的 HibernateCallback 接口) 和 HibernateDaoSupport 的使用。(P139)
40. Spring 與 JDO 和 OBJ 的整合使用較少,先跳過。Spring 支援兩種版本的 iBatis:1.3 和 2.0;1.3 的類命名為 SqlMapXxx,2.0 的類命名為 SqlMapClientXxx。對 SqlMap 的整合要配置一個 SqlMapClientFactoryBean,仍然保留 sqlMap-config.xml 檔案,并通過 configLocation 屬性配置給 SqlMapClientFactoryBean,它相當于 LocalSessionFactoryBean。關注 SqlMapClientTemplate 的配置和使用,還有一個 SqlMapClientCallbak 接口可擴充。(P149)