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