第二個範例 (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
沒有留言:
張貼留言