就JdbcTemplate 上的各個方法來看,它封裝了JDBC處理的細節,讓您不用接觸到底層的資料庫技術,然而JdbcTemplate的各個方法仍須熟悉如何使用SQL語法, 如果您想讓一些程式開發人員不用接觸到SQL語法,在Spring中,您可以進一步建立可重用的操作物件,建立之後在進行資料庫設計時,將這些設計完成的 可重用物件給開發人員使用,他們就無需接觸到SQL的細節,從他們的觀點來看,資料庫操作更接近物件導向的操作方式。
Spring提供org.springframework.jdbc.object套件,讓您以更物件導向的方式來設計資料庫操作方面的程式,您只要事先 繼承或直接實例化相對應的類別並編譯,之後就可以重複利用這個實例,呼叫它的方法來進行資料庫相關操作,而不用接觸SQL等相關細節。
org.springframework.jdbc.object.RdbmsOperation是個抽象類,代表RDBMS(Relational Database Management System)的查詢、更新、預存程序等操作,您可以使用其子類org.springframework.jdbc.object.SqlUpdate、 org.springframework.jdbc.object.MappingSqlQuery等類別,它們被設計為執行緒安全(Thread- safe),所以您可以在多執行緒的環境下重複使用這些類別的實例。
SqlFunction用來調用SQL Function,例如可以調用COUNT(),然後返回一個整數表示查詢到的資料筆數,下面是一個例子:
SqlFunction sf = new SqlFunction(
dataSource, "SELECT COUNT(*) from user");
sf.compile();
sf.run();
dataSource, "SELECT COUNT(*) from user");
sf.compile();
sf.run();
RdbmsOperation的子類別在設定好DataSource、SQL以及相關參數後,必須先呼叫compile()進行編譯,之後就可以重複使用這個實例,在設計時可以繼承SqlFunction來封裝SQL,例如修改使用 JdbcTemplate 的內容,新增一個類別如下所示:
- UserFunction.java
package onlyfun.caterpillar;
import javax.sql.DataSource;
import org.springframework.jdbc.object.SqlFunction;
public class UserFunction extends SqlFunction {
public UserFunction(DataSource dataSource) {
super(dataSource, "SELECT COUNT(*) from user");
compile();
}
}
SqlUpdate類別用來表示一個SQL的更新操作,您也可以設定相關參數,設計時也可以繼承它來進行SQL的封裝,例如:
- UserUpdate.java
package onlyfun.caterpillar;
import java.sql.Types;
import javax.sql.DataSource;
import org.springframework.jdbc.object.SqlUpdate;
public class UserUpdate extends SqlUpdate {
public UserUpdate(DataSource dataSource) {
super(dataSource,
"INSERT INTO user (name,age) VALUES(?,?)");
int[] types = {Types.VARCHAR, Types.INTEGER};
setTypes(types);
compile();
}
}
setTypes()方法用來設定SQL中"?"佔位字元所要插入的數據類型,之後執行update()方法時,可以僅指定物件陣列作為引數來進行查詢,每一個陣列值將實際取代"?"佔位字元,例如可以這麼使用:
...
SqlUpdate userUpdate = new UserUpdate(dataSource);
...
userUpdate.update(
new Object[] {user.getName(), user.getAge()});
SqlUpdate userUpdate = new UserUpdate(dataSource);
...
userUpdate.update(
new Object[] {user.getName(), user.getAge()});
SqlQuery類別表示一個SQL查詢操作,不過通常很少直接使用這個類,因為通常查詢到資料之後,會作一些處理,例如封裝為User類別的實例,您可 以使用它的子類別org.springframework.jdbc.object.MappingSqlMapping來進行這個動作,例如:
- UserQuery.java
package onlyfun.caterpillar;
import java.sql.ResultSet;
import java.sql.SQLException;
import javax.sql.DataSource;
import org.springframework.jdbc.object.MappingSqlQuery;
public class UserQuery extends MappingSqlQuery {
public UserQuery(DataSource dataSource) {
super(dataSource, "SELECT * FROM user");
compile();
}
protected Object mapRow(ResultSet rs,
int rowNum) throws SQLException {
User user = new User();
user.setId(new Integer(rs.getInt("id")));
user.setName(rs.getString("name"));
user.setAge(new Integer(rs.getInt("age")));
return user;
}
}
設計好這個類別之後,您可以這麼使用它:
...
SqlQuery userQuery = new UserQuery(dataSource);
...
List users = userQuery.execute();
SqlQuery userQuery = new UserQuery(dataSource);
...
List users = userQuery.execute();
執行完execute()方法後,實際上傳回的List中會有User類別的實例,當中並封裝了查詢後的每一筆資料。
配合以上的幾個實作,您可以再改寫一下IUserDAO介面與UserDAO實作,例如:
- IUserDAO.java
package onlyfun.caterpillar;
import java.util.List;
public interface IUserDAO {
public void insert(User user);
public List allUser();
public int count();
}
假設您是程式開發人員,有其它的負責資料庫存取方面的程式,並提供了以上的UserFunction、UserUpdate與UserQuery類別,則 您可以不用關心實際的SQL是如何下達的,可以使用UserFunction、UserUpdate與UserQuery類別來設計您的UserDAO類 別:
- UserDAO.java
package onlyfun.caterpillar;
import java.util.List;
import javax.sql.DataSource;
import org.springframework.jdbc.object.SqlFunction;
import org.springframework.jdbc.object.SqlQuery;
import org.springframework.jdbc.object.SqlUpdate;
public class UserDAO implements IUserDAO {
private SqlUpdate userUpdate;
private SqlQuery userQuery;
private SqlFunction userFunction;
public void setDataSource(DataSource dataSource) {
userUpdate = new UserUpdate(dataSource);
userQuery = new UserQuery(dataSource);
userFunction = new UserFunction(dataSource);
}
public void insert(User user) {
userUpdate.update(
new Object[] {user.getName(), user.getAge()});
}
public List allUser() {
return userQuery.execute();
}
public int count() {
return userFunction.run();
}
}
將SQL封裝重用之後,從UserDAO程式撰寫的角度來看,完全是物件操作的方式來進行,配合程式的修改,可以寫個簡單的程式來看看運作是否正常:
- SpringDAODemo.java
package onlyfun.caterpillar;
import org.springframework.context.ApplicationContext;
import org.springframework.context.
support.FileSystemXmlApplicationContext;
import java.util.List;
public class SpringDAODemo {
public static void main(String[] args) {
ApplicationContext context =
new FileSystemXmlApplicationContext(
"beans-config.xml");
User user = new User();
user.setName("just933");
user.setAge(new Integer(26));
IUserDAO userDAO =
(IUserDAO) context.getBean("userDAO");
userDAO.insert(user);
System.out.println("筆數: " + userDAO.count());
List list = userDAO.allUser();
for(int i = 0; i < list.size(); i++) {
User next = (User) list.get(i);
System.out.println("\n\tId:\t" + next.getId());
System.out.println("\tName:\t" + next.getName());
System.out.println("\tAge:\t" + next.getAge());
}
}
}