山頂洞人日記 - 回歸到最純樸的開發
DESCRIPTION
2008/05/17 TWJUG slidesTRANSCRIPT
山頂洞人日記 - 回歸到最純樸的開發山頂洞人日記 - 回歸到最純樸的開發
(Email/MSN)twitter://qing_wanghttp://blog.qing.tw
2008/5/16
審視你的需求審視你的需求
慾望總是超過真實需求 威力強大的東西難免複雜 選擇開發工具要在複雜度與威力之間選擇一個適合你
的平衡點
山頂洞人過的日子山頂洞人過的日子
WinCVS EditPlus Ant MySQL Tomcat JavaDoc of API
簡易級 Java Web 應用程式開發簡易級 Java Web 應用程式開發
不用 IDE 用 Editplus 來編輯原始碼 用 WinCVS 來做 project browsing 用 Ant 來做自動化建構
用 JSP 來寫 action 不用 Struts 不用 Spring
利用 LWDBA 來存取資料庫 不用 Hibernate 不用 EJB
關於 Ant關於 Ant
為各種類型的專案建立不同 build.xml 的 template Library Web applications Standalone application
每次建立新的專案時,依照 template 建立固定的目錄結構
瀏覽專案瀏覽專案
問題在設計問題在設計
問題不在你使用什麼 framework 問題在於你的設計對不對
劃分出系統架構中的各層劃分出系統架構中的各層
Presentation JSP 實作
Action JSP/Servlet 實作 使用 JSP 的優點在於 script language 的動態優勢
Façade 封裝事務邏輯 一般人最欠缺的
Data Access Layer LWDBA
何謂 Facade何謂 Facade
Façade 就是建築物正面的入口 The Façade pattern simplifies access to a related sets of
objects by providing one object that all objects outside the set use to communicate with the set.
你需要的只是 Code Gen 嗎?你需要的只是 Code Gen 嗎?
許多 framework 會強調 CRUD 應用程式的快速建立 可是…
許多應用程式的本質並不在 CRUD CRUD 程式碼的快速產生,似乎只對開發 ERP 之類的
系統比較有幫助
有些 Web Application 的問題在於有些 Web Application 的問題在於
問題在於設計 缺乏了 Façade layer 使用 Struts 之類的 framework 來實作 MVC 使用諸如 Hibernate 的 framework 存取資料 事務邏輯未封裝 於 Action 類別中直接操作 DAO
問題所在
LWDBALWDBA
輕量級的資料庫存取( Light-Weight Database Access )
目標:簡化存取關聯性資料庫的動作,提供最普遍的資料存取需求
No ORM, No Code Gen
對資料庫存取的需求對資料庫存取的需求
容易設定 支援 Connection Pooling 簡化 SQL 操作 簡易的 DAO 支援 Query Caching
資料庫的設定資料庫的設定
記錄於 CLASSPATH 中的 system.properties
lwdb.pool.default.type=mysql
lwdb.pool.default.driverClassName=org.gjt.mm.mysql.Driver
lwdb.pool.default.driverURL=jdbc:mysql://localhost:3306/lwdba
lwdb.pool.default.userName=root
lwdb.pool.default.password=root
lwdb.pool.default.maxConnectionCount=32
lwdb.pool.default.encoding=UTF-8
lwdb.pool.default.sqlFile=sql
LWDBA 對 SQL 的態度LWDBA 對 SQL 的態度
一般人不在程式中使用 SQL 的原因? 資料庫相依性 schema change 帶來的影響
LWDBA 對 SQL statement 的觀點 在程式中使用 SQL statement 但在程式中看不到 SQL statement
做法 SQL statement composer SQL 抽離至外部的設定檔
SQL 操作 - DBRow (1/3)SQL 操作 - DBRow (1/3)
tw.qing.lwdba.DBRow public DBRow(String _tableName, String _pkName) public DBRow(String _tableName, String _pkName[]) public void setColumn(String columnName, Object value) public Object getColumn(String columnName) public void removeColumn(String columnName) public HashMap getRow() public void setRow(HashMap hm)
SQL 操作 - DBRow (2/3)SQL 操作 - DBRow (2/3)
public String toInsertString() public String toDeleteString() public String toUpdateString() public String toQueryString()
SQL 操作 - DBRow (3/3)SQL 操作 - DBRow (3/3)
DBRow dr = new DBRow("Customer", "seqNo");
dr.setColumn("name", name);
dr.setColumn("phone", phone);
dr.setColumn("address", address);
System.out.println(dr.toInsertString());
SQL 操作 - SQLManager (1/4)SQL 操作 - SQLManager (1/4)
SQLManager 是 lwdba 為了避免將 SQL 敘述 hardcode在程式中的類別
SQLManager 會依據 system.properties 中所設定的sqlFile 來決定實際使用的 SQL 敘述設定檔 例如: sql.properties
針對不同的資料庫組態,都提供一份外掛的 SQL 敘述設定檔
程式中若想使用 SQL 敘述,則務必透過 SQLManager來取得 SQL 敘述
當系統欲切換所使用的資料庫類型時,便毋需徹底修改程式中漫於四處的 SQL 敘述
SQL 操作 - SQLManager (2/4)SQL 操作 - SQLManager (2/4)
SQL 設定檔中的每一行文字行皆代表一組 SQL 敘述,並且皆為 name=value 的對應 例如: user.getUserPassword=select password from
UserAccount where id={0}
SQL 操作 - SQLManager (3/4)SQL 操作 - SQLManager (3/4)
SQL 敘述的命名,除了 SQL 敘述本身的意義之外,在前頭冠上子系統(對應至 Facade )的名稱
SQL 敘述中如果有參數的部份,是程式執行過程中動態傳入的,以 {0} 、 {1} 、…、 {n} 來依序代表傳入的第 0 個、第 1 個、以及第 n 個參數
在撰寫 SQL 敘述時,大小寫有別
SQL 操作 - SQLManager (4/4)SQL 操作 - SQLManager (4/4)
SQLManager 提供 getSQL()族系的方法來取得 SQL 設定檔的內容String getSQL(String key)String getSQL(String key, Object arg)String getSQL(String key, Object arg1, Object arg2)String getSQL(String key, Object arg1, Object arg2,
Object arg3)String getSQL(String key, Object arg1, Object arg2,
Object arg3, Object arg4)String getSQL(String key, Object[] arg)
存取 Database - DBFacade存取 Database - DBFacade
tw.qing.lwdba.DBFacade DBFacade() DBFacade(String poolName) public QueryResult sqlQuery(String query) public int sqlUpdate(String update) public QueryResult sqlQuery(String query, int idxRow, int
count, boolean fReturnTotal) public ArrayList sqlQueryRows(String query) public ArrayList sqlQueryRows(String query, int idxRow,
int count)
查詢結果 - QueryResult查詢結果 - QueryResult
tw.qing.lwdba.QueryResult public ArrayList getRows() public int getTotalRowCount()
取得查詢結果取得查詢結果
LWDBA 將查詢結果置於 ArrayList 中 ArrayList 中的每個元素都是 HashMap
用 HashMap 表示 ResultSet 中的一筆結果 HashMap即為通用性質的 DAO 可直接將 ArrayList 及 HashMap整合快取系統
取得查詢結果 - 範例取得查詢結果 - 範例
StatisticsFacade facade = StatisticsFacade.getInstance();
ArrayList al = PPTVStatisticsFacade.listStatistics(n);
<%
for(int i=0;i<al.size();i++)
{
HashMap hm = (HashMap) al.get(i);
%>
<tr>
<td><%=hm.get("seqNo")%></td>
<td><%=hm.get("uid")%></td>
<td><%=hm.get("remoteHost")%></td>
<td><%=hm.get("type")%></td>
<td><%=hm.get("createTime")%></td>
</tr>
<%
}
%>
基於 LWDBA 的設計基於 LWDBA 的設計
依據資料的處理特性,劃分你的子系統 AdFacade AnnouncementFacade HotelFacade MemberFacade OrderFacade ZipCodeFacade …
撰寫 Facade撰寫 Facade
繼承自 DBFacade 參考 PPTVStatisticsFacade
使用 Façade 的優點使用 Façade 的優點
將事務邏輯封裝於特定的層次 Action class 不再充斥著事務邏輯
降低相依性 提昇因為變動所造成的影響
Action class 所面對的是 business service ,而非直接操作資料
Thanks!Q&A
Thanks!Q&A