这天气,热的我满头大蒜。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)。(通过网络爬虫或转载的文章,常常丢失流程图、时序图,格式错乱等,仍是看原版的比较好)