2012年9月26日 星期三

存貨管理系統 - MySQL (Part VI):刪除

第二個範例 (Part VI):刪除

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

請勿轉貼
看其他教材

刪除存貨資料

刪除存貨資料的工作也是分成兩個主要的步驟,而且其步驟跟之前的 add() 和 update() 的程式碼類似:若使用者點選某一項工作,被選擇的工作項目以及 其相關值,會被複製到相對應的輸入欄位(這步驟與 update() 的第一個部分 相同);然後,等到使用者點選"刪除"按鈕,程式需要把資料從資料庫中刪除, 然後把輸入欄位內的資料清除(清除資料的部分跟 add() 的最後工作相同)。 首先,因為第一個步驟的工作與 update() 相同,因此程式碼不需要做任何 更動。然後,我們需要註冊以及定義使用者點選"刪除"按鈕時的事件處理機制。 在本範例中,該事件會觸發 delete() 方法,所以 我們必須更改刪除的按鈕標籤如下:
<button label="刪除" width="46px" height="24px" onClick="delete()"/>
跟其他 Java 程式相同,請在 <zscript> 標籤內加入 delete() 方法如下:
  void delete() {
    try {
      Class.forName("com.mysql.jdbc.Driver");
      conn = DriverManager.getConnection("jdbc:mysql://127.0.0.1/eric", "jlu", "newpasswd");
      stmt = conn.createStatement();
      String dSQL = "delete from Product where id=" + num.value;
      if (stmt.executeUpdate(dSQL) &lt;= 0)
        throw new SQLException("資料刪除失敗");
    } catch (SQLException e) {
      e.printStackTrace();
    } finally {
      try {
        stmt.close();
      } catch (SQLException e) {
        e.printStackTrace();
      }
      try {
        conn.close();
      } catch (SQLException e) {
        e.printStackTrace();
      }
    }

    // 下列兩個敘述的順序不可以對調
    // 確保刪除的資料也從 box 和 allItems 內消失
    allItems.remove(box.getSelectedIndex());
    box.removeItemAt(box.getSelectedIndex());
    clearData();
  }

  void clearData(){
    // 清除輸入欄位
    num.value = null;
    name.value = null;
    price.value = null;
    qty.value = null;
  }
從程式碼中,我們可以清楚的看出,資料刪除分成三個動作:第一個動作 就是把使用者選擇的 Product 物件從資料庫中刪除(其中包含資料庫的連結 以及 SQL 的 delete 指令);第二個動作就是把使用者選擇的 Product 物件從 allItems 以及 box 中刪除;刪除的方式是利用 Listbox 物件的 getSelectedIndex() 來決定該物件的索引位置,然後分別利用 remove(索引位置) 和 removeItemAt(索引位置) 把該物件從 allItems 和 box 刪除;第三個動作就是把輸入欄位的值清除, 由於這一段程式碼跟 add() 重複,為了降低維護成本,我們將這個動作的 四個敘述包成一個 clearData() 方法,然後在 delete() 以及 add() 的最後 呼叫該方法。(請記得將 add() 方法做適當的修改) 以下的執行畫面為將之前 ccc 的資料刪除後的結果:
為了方便起見,我們把整個存貨管理的程式碼列示如下:
<?xml version="1.0" encoding="Big5"?>
<window title="存貨管理系統" width="640px" border="normal" mode="highlighted">
<zscript>
  // 除了方法的部分,其他的部分只會執行一次
  import java.sql.*;
  import java.util.*;


  Statement stmt = null;
  Connection conn = null;
  List allItems = new ArrayList();
  try {
    Class.forName("com.mysql.jdbc.Driver");
    conn = DriverManager.getConnection("jdbc:mysql://127.0.0.1/eric", "jlu", "newpasswd");
    stmt = conn.createStatement();
    ResultSet rs = stmt.executeQuery("select * from Product");

    Product p;
    while(rs.next()) {
      p = new Product();
      p.setId(rs.getInt(1));
      p.setName(rs.getString(2));
      p.setPrice(rs.getDouble(3));
      p.setQty(rs.getInt(4));
      allItems.add(p);
    }
  } catch (SQLException e) {
    e.printStackTrace();
  } finally {
    try {
      stmt.close();
    } catch (SQLException e) {
      e.printStackTrace();
    }
    try {
      conn.close();
    } catch (SQLException e) {
      e.printStackTrace();
    }
  }

  // 資料新增 ==========================================================
  void add() {
    // 確保新增的資料也在 allItems 內
    Product newp = new Product(num.value.intValue(), name.value, 
                               price.value.doubleValue(), qty.value.intValue());
    allItems.add(newp);

    // 經資料新增至資料庫
    try {
      Class.forName("com.mysql.jdbc.Driver");
      conn = DriverManager.getConnection("jdbc:mysql://127.0.0.1/eric", "jlu", "newpasswd");
      stmt = conn.createStatement();
      String iSQL = "insert into Product values(" + num.value + ",'" +                           
                     name.value + "'," + price.value + "," + qty.value + ")";
      if (stmt.executeUpdate(iSQL) &lt;= 0)
        throw new SQLException("資料新增失敗");
    } catch (SQLException e) {
      e.printStackTrace();
    } finally {
      try {
        stmt.close();
      } catch (SQLException e) {
        e.printStackTrace();
      }
      try {
        conn.close();
      } catch (SQLException e) {
        e.printStackTrace();
      }
    }

    // 將新增資料形成一個 Listitem 物件(或者節點) 
    Listitem li = new Listitem(); 
    li.setValue(newp);  // 在之後的 update, delete 會用到
    li.appendChild(new Listcell(num.value.toString())); 
    li.appendChild(new Listcell(name.value)); 
    li.appendChild(new Listcell(price.value.toString())); 
    li.appendChild(new Listcell(qty.value.toString())); 

    // 將 Listitem 物件變成 box 的子節點
    // box 是 listbox 的 id 值
    box.appendChild(li);

    // 清除輸入欄位
    clearData();
  }

  // 資料修改 ==========================================================
  void move() {
    // 確保修改的資料也在 allItems 內
    Product p = (Product) box.selectedItem.value;
    num.value = p.getId();
    name.value = p.getName();
    price.value = new java.math.BigDecimal(p.getPrice());
    qty.value = p.getQty(); 
  }

  // update()
  void update(){
    // 修改 box 和 allItems 物件的內容
    Product upp = (Product) box.selectedItem.value;
    upp.setId(num.value.intValue());
    upp.setName(name.value);
    upp.setPrice(price.value.doubleValue());
    upp.setQty(qty.value.intValue());
    allItems.set(box.getSelectedIndex(), upp);

    // 修改資料庫的內容
    try {
      Class.forName("com.mysql.jdbc.Driver");
      conn = DriverManager.getConnection("jdbc:mysql://127.0.0.1/eric", "jlu", "newpasswd");
      stmt = conn.createStatement();
      String uSQL = "update Product set name='" + name.value + "', price=" + price.value + 
                    ", qty=" + qty.value + " where id=" + num.value;
      if (stmt.executeUpdate(uSQL) &lt;= 0)
        throw new SQLException("資料新增失敗");
    } catch (SQLException e) {
      e.printStackTrace();
    } finally {
      try {
        stmt.close();
      } catch (SQLException e) {
        e.printStackTrace();
      }
      try {
        conn.close();
      } catch (SQLException e) {
        e.printStackTrace();
      }
    }

    // 修改 listbox 的內容
    List children = box.selectedItem.children;
    ((Listcell)children.get(0)).label = num.value.toString();
    ((Listcell)children.get(1)).label = name.value;
    ((Listcell)children.get(2)).label = price.doubleValue().toString();
    ((Listcell)children.get(3)).label = qty.value.toString(); 
  }

  // 資料刪除 =========================================================
  void delete() {
    try {
      Class.forName("com.mysql.jdbc.Driver");
      conn = DriverManager.getConnection("jdbc:mysql://127.0.0.1/eric", "jlu", "newpassw");
      stmt = conn.createStatement();
      String dSQL = "delete from Product where id=" + num.value;
      if (stmt.executeUpdate(dSQL) &lt;= 0)
        throw new SQLException("資料刪除失敗");
    } catch (SQLException e) {
      e.printStackTrace();
    } finally {
      try {
        stmt.close();
      } catch (SQLException e) {
        e.printStackTrace();
      }
      try {
        conn.close();
      } catch (SQLException e) {
        e.printStackTrace();
      }
    }

    // 下列兩個敘述的順序不可以對調
    // 確保刪除的資料也從 allItems 內消失
    allItems.remove(box.getSelectedIndex());
    box.removeItemAt(box.getSelectedIndex());
    clearData();
  }

  // ==============================================================
  void clearData(){
    // 清除輸入欄位
    num.value = null;
    name.value = null;
    price.setText("");
    qty.value = null;
  }

</zscript>
  <listbox id="box" multiple="true" rows="4" onSelect="move()">
    <listhead>
      <listheader label="料號" width="50px" />
      <listheader label="品名" />
      <listheader align="right" label="價格" width="60px" />
      <listheader align="right" label="數量" width="60px" />
    </listhead>
    <listitem forEach="${allItems}" value="${each}">
      <listcell label="${each.id}"/>
      <listcell label="${each.name}"/>
      <listcell label="${each.price}"/>
      <listcell label="${each.qty}"/>
    </listitem>
  </listbox>
  <groupbox>
    <caption label="存貨管理"/>
    料號: <intbox id="num" cols="5" />
    品名: <textbox id="name" cols="25" />
    價格: <decimalbox id="price" cols="8" />
    數量: <intbox id="qty" cols="8" />
    <div>
    <button label="新增" width="46px" height="24px" onClick="add()"/>
    <button label="修改" width="46px" height="24px" onClick="update()"/>
    <button label="刪除" width="46px" height="24px" onClick="delete()"/>
    </div>
  </groupbox>
</window>
我們的範例程式到此已經介紹完畢,可是我們要提醒讀者:這個系統只是 設計給單一使用者的;也就是說,這個系統的設計是假設一次只有一個使用者 在使用。試試看:打開兩個瀏覽器的視窗,然後分別開啟我們剛剛設計好的系統, 並分別在兩個視窗中新增資料,請觀察新增的資料是否立即反應再另一個視窗中。 練習題: 請新增一個"清除"的按鈕,使用者點選它之後,會把所有欄位的輸入 或者選擇的資料清除。

Written by: 國立中興大學資管系呂瑞麟 Eric Jui-Lin Lu





沒有留言:

張貼留言