如何用JDK8實作一個小型的關聯式資料庫系統

16,403 views

Published on

Java Developer Day Taipei 2014

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

No Downloads
Views
Total views
16,403
On SlideShare
0
From Embeds
0
Number of Embeds
13,366
Actions
Shares
0
Downloads
86
Comments
0
Likes
17
Embeds 0
No embeds

No notes for slide

如何用JDK8實作一個小型的關聯式資料庫系統

  1. 1. 如何用JDK8實作一個小型的關聯式 資料庫系統 Kishida Naoki 2014-8-1 Taipei Java Developer Day
  2. 2. 自己介紹 ● きしだ なおき(Kishida Naoki) ● 来了日本的福岡 ● 自由工作者
  3. 3. Blog/SNS ● Twitter – https://twitter.com/kis ● 部落格(きしだのはてな) – http://d.hatena.ne.jp/nowokay/
  4. 4. 福岡 ● 日本的西邊 ● 九州的北邊 ● 九州=大概跟台灣一樣大
  5. 5. 福岡 ● 從福岡到東京跟從福岡到臺北(飛機兩個小時)
  6. 6. 内容 ● 自製資料庫 ● 實作 – Java 8 使用到的功能 – 其他程式庫
  7. 7. 自製的資料庫 ● 主要用途是為了學習 ● 關聯式資料庫 ● 沒有資料形態 ● 單執行 – 多執行是複雜 ● 沒有網路 ● 記憶體上運作 – 不會存取到檔案系統 ● github – https://github.com/kishida/sqlparser
  8. 8. 資料庫的構造 ● Parser ● Planner ● Optimizer(最佳化) – Index ● Executor – Transaction
  9. 9. Parser ● 字串表示的 SQL 剖析 ● 製作 AST 抽象語法樹 ● 使用了 JParsec 來實作
  10. 10. Planner ● 抽象語法樹後 生邏輯執行計劃產 ● 邏輯執行計劃 – 詢的處理順序,用關聯式代數表示查 ● 關聯式代數 – 關聯式資料庫的基礎
  11. 11. Optimizer ● 將邏輯執行計劃製作物理執行計劃 ● 最佳化 – 節省不必要的處理 – 決定要使用的 index ● 規則為基礎的演算法 – 用來設定好規則使用 index – 難支援複雜的 詢查 – 依照資料的分佈狀況,效率不好的狀況 →cost based 的演算法
  12. 12. 物理執行計劃執行 ● Transaction ● MVCC – MultiVersionConcurentControl ● 沒 commit 的資料不會被其他 transaction 看到
  13. 13. Java8的効能 ● Stream ● Optional
  14. 14. ● 生新的產 List ● 將List 中的資料處理後 生新的產 List – fields 的 List – 所有 執行值 eval 的方法 List<Value> result = new ArrayList<>(); for(Field f : fields){ result.add(eval(f)); }
  15. 15. ● 生新的產 List ● 用Stream ● 這種類似處理非常多 ● 使用 Stream 可以減輕很多負擔 List<Value> result = fields.stream() .map(f -> eval(f)) .collect(toList());
  16. 16. ●判斷List ● List 的所有元素是否都符合條件的判斷 – conditions 的 List – 元素在使用 hasOr – 所有true 的話就 return boolean result = true; for(Condition c : conditions){ if(!hasOr(c)) result = false; } if(result) return;
  17. 17. ●判斷List ● 使用Stream – 一行就可以 – 可以在 if 直接使用 – 減少不必要的 result 變數 – 可以減少一些邏輯上出錯的問題 if(conditions.stream().allMatch(c -> hasOr(c))){ return; }
  18. 18. Optional ● 表示有沒有 的型別值 ● Scala→Optiona、Haskell→Maybe ● 通常使用 null – 忘記做 null 檢 →查 NullPointerException – 從程式碼型別上根本就分辨不出來,變數有沒 有可能被指定成 null 的狀況
  19. 19. Optional ● ex:BufferedReader – readLine ● 沒有資料可以讀時會回傳 null ● 不會知道他有可能回傳 null ● 必須認真看文件 – 文件 ● 忘記寫 ● 常常 懶沒寫偷 – 忘記檢查 null →NullPointerException ● 使用 Optional 就可以減少這類 NullPointerException 的狀況
  20. 20. Optional 的使用方法 ● 建立 Optional – Optional.of(value) – null 的時候, 會 生產 NullPointerException – 參數不為 null 時才可以使用 ● 不知道是不是值 null – Optional.ofNullable(value) ● 表示沒有值 – Optional.empty()
  21. 21. 從 Optional 取得值1 ● get() – 沒有值,丟出 NoSuchElementException – 請儘量不要這樣使用 ● orElse(defaultValue) – 沒有 時會回傳值 defaultValue
  22. 22. 從 Optional 取得值2 ● orElseGet(() -> defualtValue) – defaultValue 的計算可能會花一些時間 – 傳入一個型別為 Supplier – 使用 lambda 式 – 沒有 的時候才會執行值 – 只有在需要時才執行的動作 ● 延遲執行(Lazy Execution)
  23. 23. Optional 有 得時候才會想要執行某值 些動作 ● 判斷有沒有值 ● isPresent() – 有 →值 true – 沒有值(empty)→false ● 不是 Java 8 的風格 Optional<String> ostr = Optional.ofNullable(str); if(ostr.isPresent()){ System.out.println(ostr.get().length()); }
  24. 24. Optional 有 得時候才會想要執行某值 些動作 ● ifPresent(Consumer c) ● 只有在有 時會執行傳入的式值 ● 參數的型別是Consumer – 用 lambda 來寫 – 有 時才會執行值 Optional<String> ostr = Optional.ofNullable(str); ostr.ifPresent(s -> { System.out.println(s.length()); });
  25. 25. 轉換成其他值 值 ● map(Function<T, U>) – 傳入回傳普通 的值 lambda 式 – 回傳包著那個 得值 Optional – null的時候,變成empty – 不用擔心 NullPointerException ● flatMap(Function<T, Optional<U>) – 傳入回傳Option的 lambda式 – 回傳剛剛的 Optional Optional<String> ostr = Optional.ofNullable(str); ostr .map(String::length) .ifPresent(System.out::println);
  26. 26. 當 符合條件才要處理值 ● filter(Predicate<T>) – 條件不符合會回傳 empty Optional<String> ostr = Optional.ofNullable(str); ostr .map(String::length) .filter(len -> len < 5) .ifPresent(System.out::println);
  27. 27. map,filter,ifPresent ● 跟 map 還有 filter 之類的方法搭配處理時,非常有效果 ● map・filter・ifPresent裡面 – 保證 不會是值 null – 不用擔心NullPointerException ● 隔離有 null 的世界和沒有null 的世界 ● Optional要多打一些字 (^^ – 可以讓人寫的比較安心 – 請記得會出現 null 時就要利用 Optional
  28. 28. 程式庫 ● Lombok ● JParsec
  29. 29. Lombok ● http://projectlombok.org/ ● 可以把一些 Java 很繁雜的程式碼減少 ● Setter/Getter – 可以用 IDE 幫我們 生產 – 看起來一長串很煩 – 改也很麻煩 class Foo{ String message; public String getMessage(){ return message; } publilc void setMessage(String m){ this.message = m; } }
  30. 30. Lombok ● 清爽許多 class Foo{ @Setter @Getter String message; }
  31. 31. Lombok ● @NoArgsConstructor – 生預設建構子產 ● @AllArgsConstructor – 成員變數都要設定的建構子 ● @ToString – 生產 toString ● @EqualsAndHashCode – 生產 equals 和 hashcode ● 對應 IDE
  32. 32. JParsec ● http://jparsec.codehaus.org/ ● Parser Generator – 産生抽象語法樹 ● Haskell的Parsec移植 ● 用Java做 parser – JavaCC和Antlr需要 Java 程式碼以外的語法定義檔 – 必須特別編譯 ● 用 Java 來定義語法 – 不需要額外的檔案和編譯
  33. 33. JParsec的例 ● delete的語法定義 public static Parser<ASTDelete> delete(){ return Parsers.sequence( terms.token("delete").next(terms.token("*").optional()) .next(terms.token("from")).next(identifier()), where().optional(), (id, w) -> new ASTDelete(id, Optional.ofNullable(w))); }
  34. 34. 總結1 ● 製作資料庫非常有幫助 – 資料庫的構造 ● MySQL、PostgreSQL、Oracle ● 能大概知道他們到底在做什麼 – 能了解 SQL 的處理過程 ● 可以寫出效率更好的 SQL
  35. 35. 總結2 ● Java8很方便 – 回不去Java7 ● Optional應該多加利用 – Java8中如果出現 nullpointerexception 就太失 敗了 ● Lombok – 可以從又臭又長麻煩的程式碼中解脫 ● JParsec – 不知不覺的完成結構很大的語法定義,很有趣

×