第二個範例 (Part II)
The following examples had been tested on Mozilla's Firefox and Microsoft's IE. The document is provided as is. You are welcomed to use it for non-commercial purpose.Written by: 國立中興大學資管系呂瑞麟 Eric Jui-Lin Lu
請勿轉貼
看其他教材
資料庫的安裝與設定
為了上課方便,我們使用了 HSQLDB。 在撰寫這份範例的時候,HSQLDB 的版本為 1.8 版,請到 HSQLDB 網站下載; 下載的檔案是一個 .zip 的壓縮檔,請把它解壓縮到安裝 Tomcat 的分割區。 如果你依照我們之前的說明安裝 Tomcat 的話,那麼 HSQLDB 必須被解壓縮 到 D 槽(也就是 d:\hsqldb)。另外,請記得把 d:\hsqldb\lib\hsqldb.jar 複製到 d:\tomcat\common\lib 內;hsqldb.jar 是 HSQLDB 的 JDBC 驅動程式。 本範例所需要的表格只有一個,其資料結構如下;其中,id 為唯一的,代表 每一件事情的 ID、name 代表該事情的敘述、priority 代表處理該事情的 優先順序、以及 date 代表處理該事情的日期。| 欄位名稱 | 資料型態 |
|---|---|
| id | varchar(50) |
| name | varchar(50) |
| priority | int |
| date | date |
為了能夠在 HSQLDB 建立這樣的表格,我們必須首先啟動 HSQLDB,啟動的 方式很簡單,請在"命令提示字元"視窗內,並在 d:\hsqldb\bin 的目錄下,輸入 runUtil DatabaseManager,執行後,你會看到 如下的畫面:
create table event ( id varchar(50), name varchar(50), priority int, date date);
insert into event values('111', 'Hi', 1, '2009-05-21');
select * from event;
資料庫相關的物件
完成了資料庫的設定之後,我們採用物件導向的設計方式來設計所需要的 相關類別。由於物件的架構和關聯式資料庫的資料結構不同,因此一般來說, 好的程式設計都會利用 DAO (Data Access Object) 的物件來存取資料庫。 DAO 是一種常見的設計模式(design pattern),它的結構圖如下所示:
在應用程式實際存取的資料是以圖下方的資料對應物件來代表;若資料來源是 關聯式資料庫,而且資料結構就像 event 一樣簡單,一個資料物件即代表一筆 關聯式資料庫中的 record。資料對應物件是由 DAO 物件所產生的,所有應用程式 對資料對應物件的讀取、修改、刪除等動作,都由 DAO 物件負責完成。
依照圖片所示,資料來源其實就是範例中 HSQLDB 中的 event 表格; DAO 物件以及資料對應物件就是如下的 EventDAO 以及 Event 類別。 首先我們介紹 Event 類別;由於 Event 物件代表一筆 event 表格中的 資料,所以我們可以將 event 表格中的每一個欄位名稱對應到 Event 類別中 的資料成員,當然資料成員的資料型態儘可能跟欄位的資料型態相同。 (請注意: 資料型態在不同系統中(如 Java 和 HSQLDB) 可能有不同的表達方式,所以在實務應用上要特別小心;定義完了資料成員 之後,我們只需要為每一個資料成員設計一個對應的 accessor 和 mutator 即可。Event 的程式碼如下:
import java.util.Date;
public class Event {
private String id;
private String name;
private int priority;
private Date date;
public Event() {}
public Event(String id,String name,int priority,Date date) {
this.id = id;
this.name = name;
this.priority = priority;
this.date = date;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
public int getPriority() {
return priority;
}
public void setPriority(int priority) {
this.priority = priority;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
- HSQLDB 的 JDBC 驅動程式的名稱為 org.hsqldb.jdbcDriver,而聯結資料庫 的 URL 為 jdbc:hsqldb:file:/hsqldb/data/event。
- 不論連線資料庫或者存取資料是否成功,最後都需要把 stmt 和 conn 物件 close() 掉,這可以從方法中看得出來。切記:這些動作不能少。
- Event 中 date 的資料型態為 java.util.Date,但是在新增或者修改 date 的資料時,HSQLDB 卻只接受符合 "yyyy-MM-dd HH:mm:ss" 格式的字串,因此 程式中借用 SimpleDateFormat 把 date 物件轉成符合該格式的字串。
import java.sql.*;
import java.text.SimpleDateFormat;
import java.util.*;
public class EventDAO {
private final String url = "jdbc:hsqldb:file:/hsqldb/data/event";
private final String user = "sa";
private final String pwd = "";
public EventDAO() {
try {
// 載入 HSQLDB 的 JDBC 驅動程式
Class.forName("org.hsqldb.jdbcDriver");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
public List findAll(){
Statement stmt = null;
Connection conn = null;
List allEvents = new ArrayList();
try {
conn = DriverManager.getConnection(url, user, pwd);
stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("select * from event");
// fetch all events from database
Event evt;
while(rs.next()) {
evt = new Event();
evt.setId(rs.getString(1));
evt.setName(rs.getString(2));
evt.setPriority(rs.getInt(3));
evt.setDate(rs.getDate(4));
allEvents.add(evt);
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
return allEvents;
}
public boolean delete(Event evt){
Connection conn = null;
Statement stmt = null;
boolean result = false;
try {
conn = DriverManager.getConnection(url, user, pwd);
stmt = conn.createStatement();
if (stmt.executeUpdate("delete from event where id = '" + evt.getId() + "'") > 0)
result = true;
} catch (SQLException e) {
e.printStackTrace();
} finally {
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
return result;
}
public boolean insert(Event evt){
Connection conn = null;
Statement stmt = null;
boolean result = false;
try {
conn = DriverManager.getConnection(url, user, pwd);
stmt = conn.createStatement();
if (stmt.executeUpdate("insert into event(id,name,priority,date) " +
"values ('" + UUID.randomUUID().toString() + "','" +
evt.getName() + "'," + evt.getPriority() + ",'" +
new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(evt.getDate())
+ "')") > 0)
result = true;
} catch (SQLException e) {
e.printStackTrace();
} finally {
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
return result;
}
public boolean update(Event evt){
Connection conn = null;
Statement stmt = null;
boolean result = false;
try {
conn = DriverManager.getConnection(url, user, pwd);
stmt = conn.createStatement();
if (stmt.executeUpdate("update event set name = '" + evt.getName() +
"', priority = " + evt.getPriority() + ", date = '" +
new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(evt.getDate()) +
"' where id = '" + evt.getId() + "'") > 0)
result = true;
} catch (SQLException e) {
e.printStackTrace();
} finally {
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
return result;
}
}
請把這兩個程式碼編譯後,放置到適當的位置。如果你是依照本範例的安裝方式 進行,那麼請把 Event.class 和 EventDAO.class 放置到 d:\tomcat\webapps\xml\WEB-INF\classes 目錄內。
Written by: 國立中興大學資管系呂瑞麟 Eric Jui-Lin Lu
沒有留言:
張貼留言