public class Company { private String name; private Employee managingDirector;
public String getName() { return this.name; } public void setName(String name) { this.name = name; } public Employee getManagingDirector() { return this.managingDirector; } public void setManagingDirector(Employee managingDirector) { this.managingDirector = managingDirector; } }
public class Employee { private float salary;
public float getSalary() { return salary; } public void setSalary(float salary) { this.salary = salary; } }
然后我們使用BeanWrapper來調(diào)用這兩個(gè)bean:
Company c = new Company(); BeanWrapper bwComp = BeanWrapperImpl(c); // setting the company name... bwComp.setPropertyValue("name", "Some Company Inc."); // ... can also be done like this: PropertyValue v = new PropertyValue("name", "Some Company Inc."); bwComp.setPropertyValue(v);
// ok, let's create the director and tie it to the company: Employee jim = new Employee(); BeanWrapper bwJim = BeanWrapperImpl(jim); bwJim.setPropertyValue("name", "Jim Stravinsky"); bwComp.setPropertyValue("managingDirector", jim);
// retrieving the salary of the managingDirector through the company Float salary = (Float)bwComp.getPropertyValue("managingDirector.salary");
JDBC再封裝JDBC優(yōu)雅的封裝了底層的數(shù)據(jù)庫,但是JDBC仍然存在諸多的不變。你需要編寫大量的代碼來完成CRUD操作,而且,JDBC無論是遇到什么樣的問題,都拋出一個(gè)SQLException,這種做法在異常使用上被稱為不完備的信息。因?yàn)閱栴}可能是很復(fù)雜的,也許是數(shù)據(jù)庫連接的問題,也許是并發(fā)控制的問題,也許只是SQL語句出錯(cuò)。沒有理由用一個(gè)簡單的SQLException就搞定全部的問題了,這種做法有些不負(fù)責(zé)任。針對(duì)這兩個(gè)問題,Spring Framework提出了兩種解決方法:首先,提供一個(gè)框架,把JDBC應(yīng)用中的獲取連接、異常處理、釋放等比較通用的操作全部都集中起來,用戶只需要提供特定的實(shí)現(xiàn)就OK了。實(shí)現(xiàn)的具體細(xì)節(jié)采用的是模板方法。舉個(gè)例子,在org.springframework.jdbc.object包中,MappingSqlQuery類實(shí)現(xiàn)了將SQL查詢映射為具體的業(yè)務(wù)對(duì)象。JavaDoc中這樣寫到:Reusable query in which concrete subclasses must implement the abstract mapRow(ResultSet, int) method to convert each row of the JDBC ResultSet into an object. 用戶必須實(shí)現(xiàn)mapRow方法,這是典型模板方法的應(yīng)用。我們拿一個(gè)具體的例子來看看:
class UserQuery extends MappingSqlQuery {
public UserQuery(DataSource datasource) { super(datasource, "SELECT * FROM PUB_USER_ADDRESS WHERE USER_ID = ?"); declareParameter(new SqlParameter(Types.NUMERIC)); compile(); }
// Map a result set row to a Java object protected Object mapRow(ResultSet rs, int rownum) throws SQLException { User user = new User(); user.setId(rs.getLong("USER_ID")); user.setForename(rs.getString("FORENAME")); return user; }
public User findUser(long id) { // Use superclass convenience method to provide strong typing return (User) findObject(id); } }
JdbcTemplate template = new JdbcTemplate(dataSource); final List names = new LinkedList(); template.query("SELECT USER.NAME FROM USER", new RowCallbackHandler() { public void processRow(ResultSet rs) throws SQLException { names.add(rs.getString(1)); } });