lwdba – 開放原始碼的輕量級資料庫存取程式庫

1,521 views

Published on

介紹我們開放原始碼的資料庫存取程式庫

Published in: Technology
0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total views
1,521
On SlideShare
0
From Embeds
0
Number of Embeds
3
Actions
Shares
0
Downloads
17
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide
  • lwdba 不是要做一個無所不斬的寶劍 , 它有它設定的目標 , 以及要滿足的對象 在現存的程式庫中 , 和 lwdba 都以輕量級為目標的 , 應該就是 Commons 的 DbUtils
  • lwdba – 開放原始碼的輕量級資料庫存取程式庫

    1. 1. lwdba – 開放原始碼的輕量級資料庫存取程式庫 王建興
    2. 2. 個人簡介 <ul><li>研究興趣 </li></ul><ul><ul><li>Distributed Network Management System </li></ul></ul><ul><ul><li>Mobile Code System & Mobile Agent </li></ul></ul><ul><ul><li>P2P Networking </li></ul></ul><ul><li>開發興趣 </li></ul><ul><ul><li>Java-based Application </li></ul></ul><ul><ul><li>Multimedia Streaming </li></ul></ul><ul><ul><li>P2P Networking </li></ul></ul><ul><li>iThome 程式人專欄寫作 </li></ul><ul><li>Thinking in Java 中文版第二版及第四版的共同譯者 </li></ul><ul><li>部落格 : 程式者的胡言亂語( http://blog.qing.tw ) </li></ul>
    3. 3. Agenda <ul><li>lwdba 是什麼 </li></ul><ul><ul><li>lwdba 的適合 / 不適合應用情境 </li></ul></ul><ul><li>lwdba 的設計目標 </li></ul><ul><li>Commons DbUtils: JDBC Utility Component </li></ul><ul><li>lwdba 的取得及建構 </li></ul><ul><li>lwdba 的設定 </li></ul><ul><li>lwdba 的架構及程式設計 </li></ul><ul><li>歡迎參與 lwdba 專案 </li></ul>
    4. 4. lwdba 是什麼 <ul><li>lwdba 的名稱源自於 Light Weight DataBase Access ( 輕量級的資料庫存取 ) </li></ul><ul><li>lwdba 是一個開放原始碼的計畫 </li></ul><ul><ul><li>Apache License V2.0 </li></ul></ul><ul><li>lwdba 是基於關聯式資料庫的 Java 存取程式庫 </li></ul><ul><ul><li>它並不是一個以物件導向概念存取資料的 Java 程式庫(如 Hibernate ) </li></ul></ul><ul><ul><li>程式員透過簡單的 SQL 述句產生器,或直接利用 SQL 述句存取資料庫 </li></ul></ul>
    5. 5. 使用複雜的 Framework 的問題 <ul><li>設定複雜,一般程式員不易上手 </li></ul><ul><li>行為複雜,不僅不易學習,出了問題也不易除錯 </li></ul><ul><li>衍生大量的資料類別 </li></ul>
    6. 6. 直接使用 JDBC 的問題 <ul><li>JDBC 所提供的 API 過於原始,無法直接滿足程式員的大多數需求 </li></ul><ul><li>單純的 JDBC 缺乏 connection pooling 的機制 </li></ul>
    7. 7. 直接以 SQL 存取資料庫的問題 <ul><li>程式員直接撰寫 SQL 述句,容易直接 hardcode SQL 述句於程式之中 </li></ul><ul><li>造成程式可讀性低 </li></ul><ul><li>程式碼不易管理,也難以修改 </li></ul><ul><ul><li>倘若資料庫 schema 變動,會發生什麼事? </li></ul></ul><ul><li>所開發的程式難具資料庫可攜性 </li></ul>
    8. 8. lwdba 的設計目標 <ul><li>簡化設定 </li></ul><ul><li>減少所需的類別數 </li></ul><ul><li>支援 Connection Pooling </li></ul><ul><li>直接以關聯式資料的方式,以 SQL 的語法進行程式設計 </li></ul><ul><li>提高跨資料庫時的可移植性 </li></ul><ul><li>簡化程式設計的複雜度,容易上手 </li></ul><ul><li>支援 Query Caching </li></ul>
    9. 9. Commons DbUtils: JDBC Utility Component <ul><li>DbUtils 是 Jakarta Apache Project 下的一個程式庫 </li></ul><ul><li>DbUtils 是一小組設計用來操作 JDBC 的類別所構成的程式庫 </li></ul><ul><li>DbUtils 的設計目標包括了 </li></ul><ul><ul><li>小型(易於理解) </li></ul></ul><ul><ul><li>通透(毋需理解底層運作,只管下查詢得到資料) </li></ul></ul><ul><ul><li>快速(毋需建立大量暫時性物件) </li></ul></ul>
    10. 10. lwdba 不同於 DbUtils 之處 <ul><li>支援 Connection Pooling </li></ul><ul><li>支援 Query Caching </li></ul><ul><li>支援 SQL 述句的產生及管理 </li></ul><ul><li>對應一套進行設計時的原則 </li></ul>
    11. 11. 如何取得 lwdba <ul><li>上 lwdba 在 sourceforge 上的官方網站下載原始碼 </li></ul><ul><li>http:// lwdba.sourceforge.net / </li></ul>
    12. 12. 如何建構 lwdba <ul><li>相依程式庫 </li></ul><ul><ul><li>commons-collection-3.1 </li></ul></ul><ul><ul><li>commons-dbcp-1.2.1 </li></ul></ul><ul><ul><li>commons-logging-1.1 </li></ul></ul><ul><ul><li>commons-pool-1.2 </li></ul></ul><ul><ul><li>log4j-1.2.8 </li></ul></ul><ul><ul><li>memcached-1.4.jar </li></ul></ul><ul><ul><li>spy-2.4.jar </li></ul></ul><ul><li>利用 Apache Ant 來建構 </li></ul><ul><ul><li>http:// ant.apache.org / 上可下載 </li></ul></ul><ul><ul><li>ant package </li></ul></ul><ul><ul><li>dist/lwdba.jar <- lwdba 的程式庫 </li></ul></ul>
    13. 13. lwdba 的設定 (1/3) <ul><li>資料庫的設定皆設定於 CLASSPATH 下的 system.properties 檔案 </li></ul>lwdba.pool.default.type=mysql lwdba.pool.default.driverClassName=org.gjt.mm.mysql.Driver lwdba.pool.default.driverURL=jdbc:mysql://localhost:3306/lwdba lwdba.pool.default.userName=root lwdba.pool.default.password=root lwdba.pool.default.maxConnectionCount=32 lwdba.pool.default.encoding=UTF-8 lwdba.pool.default.sqlFile=sql Pool Name
    14. 14. lwdba 的設定 (2/3) <ul><li>lwdba.pool.default.type </li></ul><ul><ul><li>資料庫的類型,例如 mysql, mssql, oracle </li></ul></ul><ul><li>lwdba.pool.default.driverClassName </li></ul><ul><ul><li>JDBC 驅動程式的類別名稱 </li></ul></ul><ul><li>lwdba.pool.default.driverURL </li></ul><ul><ul><li>JDBC 連線 URL 字串 </li></ul></ul><ul><li>lwdba.pool.default.userName </li></ul><ul><ul><li>資料庫存取的帳號名稱 </li></ul></ul><ul><li>lwdba.pool.default.password </li></ul><ul><ul><li>資料庫存取的帳號密碼 </li></ul></ul>
    15. 15. lwdba 的設定 (3/3) <ul><li>lwdba.pool.default.maxConnectionCount </li></ul><ul><ul><li>資料庫連線 Connection Pool 的最大連線數 </li></ul></ul><ul><li>lwdba.pool.default.encoding </li></ul><ul><ul><li>預設的字元語系 </li></ul></ul><ul><li>lwdba.pool.default.sqlFile </li></ul><ul><ul><li>SQLManager 所用的 SQL 設定檔名稱 </li></ul></ul><ul><ul><li>若設定為 sql ,則代表使用 CLASSPATH 下的 sql.properties </li></ul></ul>
    16. 16. lwdba 主架構 SQLExecutorManager DBCP JDBC SQLExecutor SQLManager DBFacade DBRow 基於 lwdba 的應用程式 Database
    17. 17. lwdba 中的主要類別 <ul><li>DBRow </li></ul><ul><ul><li>簡易的 SQL 述句產生器 </li></ul></ul><ul><li>SQLManager </li></ul><ul><ul><li>管理所有的 SQL 述句 </li></ul></ul><ul><li>DBFacade </li></ul><ul><ul><li>執行 SQL 述句(查詢,更新) </li></ul></ul>
    18. 18. lwdba 如何看待 SQL statement <ul><li>一般人不在程式中使用 SQL 的原因? </li></ul><ul><ul><li>資料庫相依性 </li></ul></ul><ul><ul><li>schema change 帶來的影響 </li></ul></ul><ul><li>lwdba 對 SQL statement 的觀點 </li></ul><ul><ul><li>在程式中使用 SQL statement </li></ul></ul><ul><ul><li>但在程式中看不到 SQL statement </li></ul></ul><ul><li>做法 </li></ul><ul><ul><li>SQL statement composer </li></ul></ul><ul><ul><li>SQL statement 抽離至外部的設定檔 </li></ul></ul>
    19. 19. 在 lwdba 中得到 SQL 述句的兩種途徑 <ul><li>透過 DBRow 自動幫你產生 </li></ul><ul><ul><li>人工撰寫 SQL 述句容易出錯,也煩人 </li></ul></ul><ul><ul><li>透過一個類別來自動產生,可以省去許多功夫 </li></ul></ul><ul><li>人工手寫於 SQL 述句設定檔,透過 SQLManager 進行管理 </li></ul><ul><ul><li>再怎麼好的 SQL 述句產生器,都無法滿足所有的需求 </li></ul></ul><ul><ul><li>在實務的應用上,你可能要需要十分複雜的 SQL 述句,才能達成需求,或是提供更好的效能 </li></ul></ul>
    20. 20. DBRow - 建構式 (1/2) <ul><li>每個 DBRow 物件,都代表一筆 table 的資料(一個 row ) </li></ul><ul><li>public DBRow(String _tableName, String _pkName) </li></ul><ul><ul><li>指定欲產生的 table 名稱,及唯一的 PK 名稱 </li></ul></ul><ul><li>public DBRow(String _tableName, String _pkName[]) </li></ul><ul><ul><li>指定欲產生的 table 名稱,及複合的一組 PK 名稱 </li></ul></ul>
    21. 21. DBRow - 建構式 (2/2) <ul><li>另可指定 databaseType </li></ul><ul><ul><li>目前有特殊作用的 databaseType 為” oracle” </li></ul></ul><ul><li>public DBRow(String _tableName, String _pkName, String _databaseType) </li></ul><ul><li>public DBRow(String _tableName, String _pkName[] , String _databaseType) </li></ul>
    22. 22. DBRow - 存取整個 row 值 <ul><li>在建構 DBRow 之後, DBRow 內並無任何 column 之值,你可以逐一設定各 column 之值,或利用設定整個 row 值的方式來設定其值 </li></ul><ul><li>public void setRow(HashMap hm) </li></ul><ul><ul><li>HashMap 中的名稱及值的對映,代表欲設定之 column 及其值的對映 </li></ul></ul><ul><li>public HashMap getRow() </li></ul><ul><ul><li>將 DBRow 內各 column 的值,以 HashMap 的形式回傳 </li></ul></ul>
    23. 23. DBRow - 存取 column <ul><li>public void setColumn(String columnName, Object value) </li></ul><ul><ul><li>指定 column 名稱,及欲設定的值,設定該 DBRow 物件的 column 之值 </li></ul></ul><ul><li>public Object getColumn(String columnName) </li></ul><ul><ul><li>指定 column 名稱,取得該 DBRow 中該 column 之值 </li></ul></ul><ul><li>public void removeColumn(String columnName) </li></ul><ul><ul><li>指定 column 名稱,移除該 DBRow 中該 column 之值 </li></ul></ul>
    24. 24. DBRow - 產生 SQL 述句 <ul><li>public String toInsertString() </li></ul><ul><ul><li>產生 SQL insert 述句,可用於新增該筆資料 </li></ul></ul><ul><li>public String toDeleteString() </li></ul><ul><ul><li>產生 SQL delete 述句,可用於刪除該筆資料 </li></ul></ul><ul><li>public String toUpdateString() </li></ul><ul><ul><li>產生 SQL update 述句,可用於更新該筆資料 </li></ul></ul><ul><li>public String toQueryString() </li></ul><ul><ul><li>產生 SQL query 述句,可用於查詢資料 </li></ul></ul>
    25. 25. DBRow - 產生新增資料 SQL 述句的例子 DBRow dr = new DBRow(&quot;Customer&quot;, &quot;seqNo&quot;); dr.setColumn(&quot;name&quot;, name); dr.setColumn(&quot;phone&quot;, phone); dr.setColumn(&quot;address&quot;, address); System.out.println(dr.toInsertString()); insert into Customer(phone, address, name) values('0988168168', 'Hsinchu City, Taiwan', 'Qing')
    26. 26. DBRow - 產生刪除資料 SQL 述句的例子 <ul><li>欲刪除 Customer 表格, seqNo=123 的資料 </li></ul>DBRow dr = new DBRow(&quot;Customer&quot;, &quot;seqNo&quot;); dr.setColumn(“seqNo&quot;, 123); System.out.println(dr.toDeleteString()); 所設定的 column 會做為 where 子句中的條件
    27. 27. DBRow - 產生更新資料 SQL 述句的例子 <ul><li>Customer 表格, seqNo=123 的資料,其 phone 欄位之值原為 0935168888 ,欲更改為 0939168888 </li></ul>DBRow dr = new DBRow(&quot;Customer&quot;, &quot;seqNo&quot;); dr.setColumn(“seqNo&quot;, 123); dr.setColumn(“phone&quot;, ”0939168888”); System.out.println(dr.toUpdateString()); 只設定 PK 及欲更新的 column 即可!
    28. 28. DBRow - 產生查詢資料 SQL 述句的例子 <ul><li>欲查詢 Customer 表格中 phone 欄位值為 0939168888 的資料 </li></ul>DBRow dr = new DBRow(&quot;Customer&quot;, &quot;seqNo&quot;); dr.setColumn(“phone&quot;, ”0939168888”); System.out.println(dr.toQueryString()); 所設定的 column 會做為 where 子句中的條件
    29. 29. DBRow -建構式中 databaseType 引數的作用 <ul><li>結果 </li></ul>DBRow dr = new DBRow(&quot;Customer&quot;, &quot;seqNo&quot;, &quot;oracle&quot;); dr.setColumn(&quot;name&quot;, name); dr.setColumn(&quot;phone&quot;, phone); dr.setColumn(&quot;address&quot;, address); dr.setColumn(&quot;createdTime&quot;, new Date()); System.out.println(dr.toInsertString()); insert into Customer(phone, createdTime, address, name) values('0988168168', TO_DATE('2009-03-12 14:13:37', 'YYYY-MM-DD HH24:MI:SS'), 'Hsinchu City, Taiwan', 'Qing')
    30. 30. SQLManager <ul><li>SQLManager 是 lwdba 為了避免將 SQL 述句寫死在程式中的類別 </li></ul><ul><li>SQLManager 會依據 system.properties 中所設定的 sqlFile 來決定實際使用的 SQL 敘述設定檔 </li></ul><ul><ul><li>例如: sql.properties </li></ul></ul><ul><li>針對不同的資料庫類型( mysql, mssql, oracle ),可分別提供一份外掛的 SQL 敘述設定檔 </li></ul><ul><li>程式中若想使用 SQL 敘述,則務必透過 SQLManager 來取得 SQL 敘述 </li></ul>
    31. 31. SQL 述句設定檔 <ul><li>SQL 設定檔中的每一行文字行皆代表一組 SQL 敘述,並且皆為 name=value 的對應 </li></ul><ul><ul><li>例如: User.getUserPassword=select password from UserAccount where id={0} </li></ul></ul><ul><li>設定中的 Xxx.yyyyy 建議命名方式 </li></ul><ul><ul><li>Xxx 為子系統名稱 </li></ul></ul><ul><ul><li>yyyy 為子系統提供的服務,通常為一動作 </li></ul></ul><ul><li>上例中的 {0} 為可代入 SQL 述句的參數, 0 代表第 0 個參數,可依此類推設定 {1}, {2}, … </li></ul>
    32. 32. SQLManager 所帶來的好處 <ul><li>SQLManager 集中管理所有的 SQL 述句 </li></ul><ul><li>當系統欲切換所使用的資料庫類型時,便毋需徹底修改程式中漫於四處的 SQL 敘述 </li></ul><ul><li>當系統遭遇 schema 更動時,只需檢視此一檔案即可 </li></ul><ul><li>程式員為所使用的 SQL 述句逐一命名,所以在程式中所見,皆為 SQL 述句的名稱,而非 SQL 述句之細節資訊,更為高階並更富可讀性 </li></ul><ul><li>所採用的命名慣例,以子系統以及它所提供服務的觀點來切入資料的處理,隔離了 SQL 述句的具體實作寫法 </li></ul>
    33. 33. SQLManager - 取得 SQL 述句( 1/2 ) <ul><li>SQLManager 提供 getSQL() 族系的方法來取得 SQL 設定檔的內容 </li></ul><ul><ul><li>String getSQL(String key) </li></ul></ul><ul><ul><li>String getSQL(String key, Object arg) </li></ul></ul><ul><ul><li>String getSQL(String key, Object arg1, Object arg2) </li></ul></ul><ul><ul><li>String getSQL(String key, Object arg1, Object arg2, Object arg3) </li></ul></ul><ul><ul><li>String getSQL(String key, Object arg1, Object arg2, Object arg3, Object arg4) </li></ul></ul><ul><ul><li>String getSQL(String key, Object[] arg) </li></ul></ul>
    34. 34. SQLManager - 取得 SQL 述句( 2/2 ) <ul><li>例如 </li></ul><ul><li>得到的 sql 為 </li></ul><ul><ul><li>select password from UserAccount where id= ‘qing’ </li></ul></ul>String sql = sqlManager.getSQL(“ User.getUserPassword”, “qing”); 自動加上單引號 User.getUserPassword=select password from UserAccount where id= {0}
    35. 35. DBFacade - 何謂 Facade <ul><li>Façade 就是建築物正面的入口 </li></ul><ul><li>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. </li></ul>*Gamma et al (1995). Design Patterns: Elements of Reusable Object-Oriented Software.
    36. 36. DBFacade - 用以實作資料存取的子系統 <ul><li>在應用系統中,總是會找出若干個高度相關的資料表格,對它們所需的存取動作,存在極高的內聚力,我們可以將這些動作聚集在一起,構成一個子系統 </li></ul><ul><li>例如使用者帳戶管理可能牽扯進幾個表格 </li></ul><ul><ul><li>User :使用者帳戶資訊 </li></ul></ul><ul><ul><li>Role :角色 </li></ul></ul><ul><ul><li>Group :群組 </li></ul></ul><ul><ul><li>UserRole :使用者所屬的角色 </li></ul></ul><ul><ul><li>UserGroup :使用者所屬的群組 </li></ul></ul><ul><ul><li>UserPermission :使用者被賦予的權限 </li></ul></ul><ul><ul><li>RolePermission :角色被賦予的權限 </li></ul></ul><ul><ul><li>GroupPermission :群組被賦予的權限 </li></ul></ul><ul><li>可將對這幾個 table 主要的操作,聚集在一起,成為 UserAccountFacade </li></ul>
    37. 37. UserAccountFacade 的介面 <ul><li>Façade 提供更為高階,隱藏資料操作細節及事務邏輯的介面 </li></ul><ul><li>boolean loginUser(String id, String password) </li></ul><ul><li>boolean hasRole(String roleId) </li></ul><ul><li>boolean inGroup(String groupId) </li></ul><ul><li>boolean hasPermission(String id, String perm) </li></ul><ul><li>… </li></ul>
    38. 38. 基於子系統劃分的設計方式 <ul><li>依據資料的處理特性,劃分你的子系統 </li></ul><ul><ul><li>AdFacade </li></ul></ul><ul><ul><li>AnnouncementFacade </li></ul></ul><ul><ul><li>HotelFacade </li></ul></ul><ul><ul><li>MemberFacade </li></ul></ul><ul><ul><li>OrderFacade </li></ul></ul><ul><ul><li>ZipCodeFacade </li></ul></ul><ul><ul><li>… </li></ul></ul>
    39. 39. 基於 Façade 從事設計的優點 <ul><li>將事務邏輯封裝於特定的層次 </li></ul><ul><li>用戶端類別不再充斥著事務邏輯 </li></ul><ul><ul><li>降低相依性 </li></ul></ul><ul><ul><li>提昇因為變動所造成的影響 </li></ul></ul><ul><li>用戶端類別所面對的是一組高度相關的服務,而非直接操作資料 </li></ul><ul><ul><li>在開發 Web 應用程式的你,或許將操作資料的事務邏輯,撰寫於 Action 類別中 </li></ul></ul>
    40. 40. DBFacade - lwdba 中所有 Façade 的基礎類別 <ul><li>DBFacade 是 lwdba 中所有 Façade 類別的基礎類別 </li></ul><ul><li>DBFacade 具有兩個重要的成員 </li></ul><ul><ul><li>protected SQLExecutor sqlExecutor :可用以執行 SQL 述句 </li></ul></ul><ul><ul><li>protected SQLManager sqlManager :可用以取得 SQL 述句 </li></ul></ul>
    41. 41. DBFacade - 建構式 <ul><li>DBFacade() </li></ul><ul><ul><li>使用名為” default” 的 connection pool </li></ul></ul><ul><li>DBFacade(String poolName) </li></ul><ul><ul><li>使用 poolName 引數所指定的 connection pool </li></ul></ul><ul><ul><li>此名稱對應至 system.properties 中的設定 </li></ul></ul>lwdba.pool. default .type=mysql lwdba.pool. default .driverClassName=org.gjt.mm.mysql.Driver lwdba.pool. default .driverURL=jdbc:mysql://localhost:3306/lwdba … . lwdba.pool. default .sqlFile=sql
    42. 42. DBFacade - 進行查詢,回傳 QueryResult <ul><li>public QueryResult sqlQuery(String query) </li></ul><ul><ul><li>執行所指定的 SQL query 述句,並以 QueryResult 物件的方式回傳查詢結果 </li></ul></ul><ul><li>public QueryResult sqlQuery(String query, int idxRow, int count, boolean fReturnTotal) </li></ul><ul><ul><li>執行所指定的 SQL query 述句,並以 QueryResult 物件的方式回傳查詢結果中從第 idxRow 筆開始的資料,最多不超過 count 筆,並依據 fReturnTotal 的引數,決定是否回傳資料的總筆數 </li></ul></ul>
    43. 43. QueryResult - 用來表示一組查詢結果 <ul><li>public ArrayList getRows() </li></ul><ul><ul><li>取得所有的資料, ArrayList 中的每個元素皆為 HashMap 型別 </li></ul></ul><ul><li>public int getTotalRowCount() </li></ul><ul><ul><li>取得實際的總資料筆數 </li></ul></ul><ul><ul><li>當限定查詢範圍時(指定 idxRow 及 count ),可使用 fReturnTotal 引數指定是否回傳實際的總筆數 </li></ul></ul>
    44. 44. DBFacade - 進行查詢,回傳 ArrayList <ul><li>public ArrayList sqlQueryRows(String query) </li></ul><ul><ul><li>執行所指定的 SQL query 述句,並將查詢結果儲存於 ArrayList 中回傳 </li></ul></ul><ul><li>public ArrayList sqlQueryRows(String query, int idxRow, int count) </li></ul><ul><ul><li>執行所指定的 SQL query 述句,並以 ArrayList 回傳查詢結果中從第 idxRow 筆開始的資料,最多不超過 count 筆,無法回傳資料的總筆數 </li></ul></ul>
    45. 45. 取得查詢結果 <ul><li>lwdba 將查詢結果置於 ArrayList 中 </li></ul><ul><li>ArrayList 中的每個元素都是 HashMap </li></ul><ul><ul><li>用 HashMap 表示 ResultSet 中的一筆結果 </li></ul></ul><ul><li>HashMap 即為通用性質的 DAO </li></ul><ul><li>可直接將 ArrayList 及 HashMap 整合快取系統 </li></ul>
    46. 46. 取得查詢結果 - 範例 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(&quot;seqNo&quot;)%></td> <td><%=hm.get(&quot;uid&quot;)%></td> <td><%=hm.get(&quot;remoteHost&quot;)%></td> <td><%=hm.get(&quot;type&quot;)%></td> <td><%=hm.get(&quot;createTime&quot;)%></td> </tr> <% } %>
    47. 47. DBFacade - 更新資料 <ul><li>public int sqlUpdate(String update) </li></ul><ul><ul><li>執行 SQL update 述句( insert, delete, update, create table, … ) </li></ul></ul><ul><ul><li>回傳更新的資料筆數 </li></ul></ul>
    48. 48. 如何使用 DBFacade <ul><li>繼承 DBFacade </li></ul><ul><li>分析出系統中的子系統,找出每個子系統與底層資料表格的關聯性 </li></ul><ul><li>設計時基於系統分析的結果( User Case, User Story ),為滿足這些需求,你會為各子系統設計出一個個的 method ( business service ) </li></ul><ul><li>針對所設計出來的每個 method ,利用 DBFacade 提供的資料查詢及更新機制予以實作 </li></ul>
    49. 49. 處理交易 - TransSQLExecutor <ul><li>SQLExecutor 所執行 SQL 述句,皆為 auto commit ,也就是說,並不提供交易的能力 </li></ul><ul><li>對於一連串被視為同一交易的 SQL 述句,可利用 lwdba 的 TransSQLExecutor 執行 </li></ul><ul><li>TransSQLExecutor 為 SQLExecutor 之衍生類別 </li></ul>
    50. 50. TransSQLExecutor 與 SQLExecutor 的差異處 <ul><li>TransSQLExecutor 在建構之後、 close() 被呼叫之前,自始至終皆使用同一個 Connection 物件 </li></ul><ul><ul><li>SQLExecutor 則每次自 connection pool 取出一 Connection 物件 </li></ul></ul><ul><li>TransSQLExecutor 擴增了 commit() 及 rollback() 兩個函式,分別支援交易的提交及回繞 </li></ul>
    51. 51. TransSQLExecutor - 支援交易 <ul><li>public void commit() </li></ul><ul><ul><li>提交 </li></ul></ul><ul><li>public void rollback() </li></ul><ul><ul><li>回繞 </li></ul></ul>
    52. 52. TransSQLExecutor -處理交易的例子 TransSQLExecutor tse = new TransSQLExecutor(); DBRow dr = new DBRow(&quot;Customer&quot;, &quot;seqNo&quot;); dr.setColumn(&quot;name&quot;, “Alice&quot;); dr.setColumn(&quot;phone&quot;, &quot;0988168168&quot;); dr.setColumn(&quot;address&quot;, &quot;Hsinchu City, Taiwan&quot;); tse.executeUpdate(dr.toInsertString()); tse.rollback(); dr = new DBRow(&quot;Customer&quot;, &quot;seqNo&quot;); dr.setColumn(&quot;name&quot;, “Bob&quot;); dr.setColumn(&quot;phone&quot;, &quot;0968168168&quot;); dr.setColumn(&quot;address&quot;, &quot;Hsinchu City, Taiwan&quot;); tse.executeUpdate(dr.toInsertString()); tse.commit(); tse.close();
    53. 53. SQL 查詢結果的快取 <ul><li>許多應用程式,有對 SQL 查詢做快取的需求 </li></ul><ul><ul><li>對資料庫的複雜查詢常是應用程式效能的瓶頸 </li></ul></ul><ul><ul><li>依據應用程式的型態,許多類型的查詢 </li></ul></ul><ul><ul><ul><li>資料變動速度慢 </li></ul></ul></ul><ul><ul><ul><li>不需要百分之百的即時性 </li></ul></ul></ul><ul><ul><li>重複執行結果相同的資料庫查詢缺乏效率 </li></ul></ul><ul><li>lwdba 目前支援以 memcached 做為快取的伺服器 </li></ul>
    54. 54. memcached <ul><li>memcached 是一套分散式的快取系統 </li></ul><ul><li>最早是 Danga Interactive 為了 LiveJournal 所開發的 </li></ul><ul><ul><li>每日有上百萬個用戶, 20M 個 page views </li></ul></ul><ul><li>memcached 是由 C 所寫成,但目前有各種語言的 Client APIs </li></ul><ul><ul><li>Perl, PHP, Python, Ruby, Java, C#, C, … </li></ul></ul>
    55. 55. 取得並設置 memcached <ul><li>Unix </li></ul><ul><ul><li>下載: </li></ul></ul><ul><ul><ul><li>http://www.danga.com/memcached/download.bml </li></ul></ul></ul><ul><ul><li>安裝: </li></ul></ul><ul><ul><ul><li>參考 http://www.ajohnstone.com/archives/installing-memcached/ </li></ul></ul></ul><ul><ul><ul><li>memcached 需要 libevent </li></ul></ul></ul><ul><li>Windows </li></ul><ul><ul><li>下載( memcached for Win32 ) </li></ul></ul><ul><ul><ul><li>http://jehiah.cz/projects/memcached-win32/ </li></ul></ul></ul><ul><li>Java API </li></ul><ul><ul><li>下載 http://bleu.west.spy.net/~dustin/projects/memcached/ </li></ul></ul>
    56. 56. SQL 查詢結果的快取 - CachedQueryFacade <ul><li>public HashMap[] sqlQueryCached(String sql) </li></ul><ul><ul><li>倘若快取中無指定 sql 述句的查詢結果,或上次查詢時間已超過 10 分鐘,則進行查詢,並將結果置於快取中 </li></ul></ul><ul><li>public HashMap[] sqlQueryCached(String sql, long refreshInterval) </li></ul><ul><li>倘若快取中無指定 sql 述句的查詢結果,或上次查詢時間已超過指定的 refreshInterval ,則進行查詢,並將結果置於快取中 </li></ul>
    57. 57. CachedQueryFacade - 快取的失效與刷新 <ul><li>public void invalidateSQLQueryCached(String sql) </li></ul><ul><ul><li>令快取中的查詢結果失效 </li></ul></ul><ul><li>public HashMap[] refreshSQLQueryCached(String sql) </li></ul><ul><ul><li>強迫更新快取中的查詢結果 </li></ul></ul>
    58. 58. 使用 lwdba 於你的資料庫存取 <ul><li>簡單 </li></ul><ul><ul><li>僅操作幾個類別便能輕易的存取資料庫中的資料 </li></ul></ul><ul><li>易學 </li></ul><ul><li>直接以習慣的關聯式資料存取方式來存取資料 </li></ul><ul><li>輔以基於子系統的設計觀念來設計你的系統 </li></ul>
    59. 59. 歡迎參加 lwdba 專案或提供各種建議及指教! qing at cs.nthu.edu.tw
    60. 60. <ul><li>王建興 </li></ul><ul><ul><li>qing at cs.nthu.edu.tw </li></ul></ul><ul><ul><li>http://blog.qing.tw </li></ul></ul>Thank You

    ×