這天氣,熱的我滿頭大蒜。java
在上一篇博文《五鼠鬧東京之執行器Executor設計本來》中,已經對Executor作了比較詳細的分析,可是,測試妹紙閱讀完後,表示某些地方看不懂,絕不客氣的給我提出了兩點修改意見。web
1、看完你的Statement和PrepareStatement批處理原理圖,依然不明白爲什麼一個編譯Sql 3次,而另一個編譯Sql 1次。sql
2、對關閉Statement對象一筆帶過,不夠清晰。數據庫
我準備亡羊補牢,針對上面的兩個問題進行補充完善。
緩存
insert into students(id) values(1); insert into students(id) values(1); insert into students(id) values(2); insert into students(id) values(3);
上面的4個Sql,不管是Statement,仍是PrepareStatement,對Sql都編譯3次。由於其中第一、2條Sql是徹底相同的,只會編譯1次。
網絡
insert into students(id) values(?); // id=[1,2,3]
對於PrepareStatement,支持問號「?」佔位符,向數據庫中插入id=[1,2,3]三條記錄,對Sql只編譯1次,因爲減小了編譯次數,大幅提升了效率。
ide
Statement不支持問號「?」佔位符,向數據庫中插入id=[1,2,3]三條記錄,只能寫成下面這樣。
測試
insert into students(id) values(1); insert into students(id) values(2); insert into students(id) values(3);
因爲Sql不一樣,因此編譯3次,效率較低。spa
以上討論,是在批處理狀況下,兩者的編譯Sql表現。.net
ReuseExecutor.doFlushStatements()。
@Override public List<BatchResult> doFlushStatements(boolean isRollback) throws SQLException { for (Statement stmt : statementMap.values()) { closeStatement(stmt); } statementMap.clear(); return Collections.emptyList(); }
Reuse的Statement內,並無未執行的Sql命令,因此直接close便可。
BatchExecutor.doFlushStatements()。
@Override public List<BatchResult> doFlushStatements(boolean isRollback) throws SQLException { try { List<BatchResult> results = new ArrayList<BatchResult>(); if (isRollback) { return Collections.emptyList(); } for (int i = 0, n = statementList.size(); i < n; i++) { Statement stmt = statementList.get(i); BatchResult batchResult = batchResultList.get(i); try { // executeBatch() batchResult.setUpdateCounts(stmt.executeBatch()); //... results.add(batchResult); } return results; } finally { for (Statement stmt : statementList) { closeStatement(stmt); } currentSql = null; statementList.clear(); batchResultList.clear(); } }
BatchExecutor內保存的Statement對象內,都是有等待執行的Sql批處理命令的,因此,先執行stmt.executeBatch(),保存執行結果,而後再close。
在Executor的實現類中,只有ReuseExecutor和BatchExecutor緩存了Statement對象,因此,其餘的Executor對doFlushStatements()進行了空實現。
(Made In Visual Paradigm)
即,每當調用commit、rollback、close方法時,都會先調用doFlushStatements(),而後再commit、rollback、close。
上圖一樣適用於其餘的Executor實現類。
結語:設計原則中,有一條是「單一職責」原則,受其啓發,博文也採起「單一職責」原則,一篇博文儘可能分析一類知識點,避免跳躍性暈眩。
另外,大牛黃勇先生,搞了一個smartweb項目,大牛紅薯先生,搞了一個J2Cache項目,大牛羅果先生,更是搞了一個高大上的Tiny項目……,羨慕崇拜之餘,仍是靜下心來,夯實基礎,但願之後咱也能體驗下大牛的無敵最寂寞。
版權提示:文章出自開源中國社區,若對文章感興趣,可關注個人開源中國社區博客(http://my.oschina.net/zudajun)。(通過網絡爬蟲或轉載的文章,常常丟失流程圖、時序圖,格式錯亂等,仍是看原版的比較好)