- 浏览: 453119 次
最新评论
-
carlos23:
我想知道用WriterLogger后,里面的writer在外面 ...
论面向组合子程序设计方法 之 燃烧的荆棘 -
marsyoung:
讲的什么。。没看懂。例子太抽象。。
论面向组合子程序设计方法 之 创世纪 -
wanghhao:
优雅的方式!
论面向组合子程序设计方法 之 微步毂纹生 -
ykdsg:
有源码吗?
论面向组合子程序设计方法 之 monad -
咱不怕:
如果在一个函数中多次使用到这个不变temp对象,按照Marti ...
关于 Replace Temp With Query
公司的一个大系统的持久层一直是直接使用jdbc。在jdbc的基础上,又自制了一个简陋的cache。
每个持久功能的实现都比较类似,大致相当于这样:
当然,各个功能的实现不完全一样,有的有事务,有的没有;有的忘了关闭statement,有的忘了checkIn connection;有的在出现Error的时候忘了rollback。等等等等。
dao层的代码就是调用这些不同的jdbc代码,然后再包上一层HashMap做cache:
当然,还要自己实现cloneAccount()。
所有对Account, Contribution, Plan之类的cache代码也类似。
后来鉴于偶尔出现资源泄漏问题,一个程序员写了一个jdbc模板,长成这个样子:
然后上面的代码可以简化为仅仅重载这四个抽象函数:
getStatement负责取得某个特定的sql statement;populateStatement负责填充参数;processResult负责把ResultSet转换成domain object;isTransactional制定是否使用事务。
介绍了这么多背景情况,希望你已经看到了,原来的直接jdbc方法是非常繁琐,容易出错,代码量大,而且重复很多。
这个PersisterCommand也有很多局限:
1。它只能处理一个connection一个statement,不能做batch。
2。它在Error出现的时候没有rollback。
3。子类仍然要针对jdbc api写一些有重复味道的代码。
4。代码不容易单元测试。因为ConnectionManager.checkOut()和ConnectionManager.checkIn()都是写死的。
另外,这个自制的cache也是一个重复代码的生产者。
针对这种情况,我本来想继续重构,弄出一个CacheManager和更灵活的jdbc模板。但是后来一想,倒还不如直接用ibatis来得好。毕竟ibatis已经是被业界广泛使用的工具,总比自己制造轮子强。而且,相比于hibernate,ibatis也有更贴近我们现在的模型和使用习惯的优势。
我的一个同事(公司的元老),开始是对ibatis很感兴趣的。
可惜的是,当我完成了ibatis的集成,他试用了一下之后就改变了主意。这个同事在项目组甚至整个公司说话都是很有分量的,不说服他,推广ibatis就面临夭折的可能。
我的ibatis的集成长成这个样子:
这样,除非用户代码调用openSession(),其它的函数都自动处理了Session的关闭。事务处理用一个boolean参数来控制也相当简单。
上面的那么多jdbc代码和cache代码最终就可以直接变成:
那么同事对这个东西的意见在哪里呢?
1。他和另外一个同事为调试一个使用了ibatis的程序bug花了一天时间。后来把ibatis删掉,直接用jdbc就修好了。
当时我在休假,回来后一看,这个bug首先是一个stored proc的bug。他们花很多时间在ibatis里面找问题其实都是瞎耽误工夫;其次,在他们到处找ibatis的问题的时候,注释掉了两行关键代码,后来忘了放回来,所以才发生stored proc修好后,ibatis代码还是不工作,直到换了jdbc才修好。
虽然我解释了原因,同事坚持认为ibatis过于复杂。如果它花了他这么长时间来debug,别人也有可能因为种种原因花很多时间来debug别的问题。
2。ibatis只支持一个参数。这个我也解释了,你可以用java bean或者Map。可是同事认为这也是ibatis的学习曲线问题。如果采用,就要求大家都去学ibatis doc才行。
3。同事原来期待的是象Active Record那样的革命性的提高和简化。象ibatis这样还是要进行手工mapping的,对他来说就是没什么太大意义。他不觉得在java里面做这个mapping有什么不好。(我想,也许Hibernate对他更有吸引力。不过把这个系统转换为Hibernate这工作量可大多了)
4。当我说ibatis可以节省很多资源管理的重复代码时,同事说他可以用PersisterCommand。我说PersisterCommand的这些局限性的时候,他说,他不在乎。大不了直接写jdbc。
5。一致性问题。如果同时用jdbc和ibatis,大家就要学两个东西,造成混淆。而如果要把所有东西都换成ibatis,工作量是一个方面,所有的人都要学习ibatis这个代价也是很大的。
6。同事认为cache的那点重复代码无所谓。即使有一些降低cache hit ratio的bug也不是什么大不了的。
最后无法达成统一意见。因为你说什么优点的时候,他只要一句“我不在乎”你就无话可说了。
在这些论点里面,我也认可ibatis的学习曲线和一致性问题。可是,总不能就永远任由这个持久层代码这么滥下去吧?在java这个领域里,我几乎完全相信不可能出现Active Record等价的东西的。而无论Hibernate还是jpa,只怕都是有不下于ibatis的学习曲线和更高的从遗留系统移植的代价吧?
越来越感觉自己不是一个合格的architect。因为我缺乏说服人的能力。
你怎么看这个问题呢?
自己加班也不成地。我们要求所有代码必须pair,得有人跟我一起自愿加班才行。
何况,自愿加班也解决不了别人要学习ibatis的问题。说实话,ibatis的xml mapping语法还不是十分钟就能搞明白的。
每个持久功能的实现都比较类似,大致相当于这样:
MyProprietaryConnection conn = ConnectionManager.checkOut(Database.DB_NAME); try { PreparedStatement stmt = conn.getPreparedStatement("some statement id, identifying a sql statement in an xml file"); stmt.setString(1, "param 1"); stmt.setInt(2, param2); ... try { ResultSet resultSet = stmt.executeQuery(); try{ while(resultSet.next()) { ... } } finally { resultSet.close(); } } finally { stmt.close(); } } finally { ConnectionManager.checkIn(conn); }
当然,各个功能的实现不完全一样,有的有事务,有的没有;有的忘了关闭statement,有的忘了checkIn connection;有的在出现Error的时候忘了rollback。等等等等。
dao层的代码就是调用这些不同的jdbc代码,然后再包上一层HashMap做cache:
Object cacheKey = ...; synchronized(cache) { Account acct = (Account)cache.get(cacheKey); if(acct == null) { acct = runJdbcForAccount(...); cache.put(cacheKey, acct); } return acct.cloneAccount(); }
当然,还要自己实现cloneAccount()。
所有对Account, Contribution, Plan之类的cache代码也类似。
后来鉴于偶尔出现资源泄漏问题,一个程序员写了一个jdbc模板,长成这个样子:
abstract class PersisterCommand { protected abstract void populateStatement(PreparedStatement stmt); protected abstract Object processResult(ResultSet resultSet); protected abstract boolean isTransactional(); protected abstract PreparedStatement getStatement(); public Object run() { MyProprietaryConnection conn = ConnectionManager.checkOut(Database.DB_NAME); try { PreparedStatement stmt = getStatement(); populateStatement(stmt); ... try { if(isTransactional()) { conn.startTransaction(); } ResultSet resultSet = stmt.executeQuery(); try{ Object result = processResult(resultSet); if(isTransactional()) { conn.commitTransaction(); } return result; } catch(Exception e){ if(isTransactional()) conn.rollbackTransaction(); throw e; } finally { resultSet.close(); } } finally { stmt.close(); } } finally { ConnectionManager.checkIn(conn); } } }
然后上面的代码可以简化为仅仅重载这四个抽象函数:
getStatement负责取得某个特定的sql statement;populateStatement负责填充参数;processResult负责把ResultSet转换成domain object;isTransactional制定是否使用事务。
介绍了这么多背景情况,希望你已经看到了,原来的直接jdbc方法是非常繁琐,容易出错,代码量大,而且重复很多。
这个PersisterCommand也有很多局限:
1。它只能处理一个connection一个statement,不能做batch。
2。它在Error出现的时候没有rollback。
3。子类仍然要针对jdbc api写一些有重复味道的代码。
4。代码不容易单元测试。因为ConnectionManager.checkOut()和ConnectionManager.checkIn()都是写死的。
另外,这个自制的cache也是一个重复代码的生产者。
针对这种情况,我本来想继续重构,弄出一个CacheManager和更灵活的jdbc模板。但是后来一想,倒还不如直接用ibatis来得好。毕竟ibatis已经是被业界广泛使用的工具,总比自己制造轮子强。而且,相比于hibernate,ibatis也有更贴近我们现在的模型和使用习惯的优势。
我的一个同事(公司的元老),开始是对ibatis很感兴趣的。
可惜的是,当我完成了ibatis的集成,他试用了一下之后就改变了主意。这个同事在项目组甚至整个公司说话都是很有分量的,不说服他,推广ibatis就面临夭折的可能。
我的ibatis的集成长成这个样子:
public interface Action { Object run(SqlMapSession session); } public class IbatisPersistence { public SqlMapSession openSession(); public Object queryForObject(String key); public List queryForList(String key); public int update(String key, boolean useTransaction); public int delete(String key, boolean useTransaction); public int update(String key); public int delete(String key); public Object run(Action action); }
这样,除非用户代码调用openSession(),其它的函数都自动处理了Session的关闭。事务处理用一个boolean参数来控制也相当简单。
上面的那么多jdbc代码和cache代码最终就可以直接变成:
Accunt acct = persistence.queryForObject("getAccountById", accountId);
那么同事对这个东西的意见在哪里呢?
1。他和另外一个同事为调试一个使用了ibatis的程序bug花了一天时间。后来把ibatis删掉,直接用jdbc就修好了。
当时我在休假,回来后一看,这个bug首先是一个stored proc的bug。他们花很多时间在ibatis里面找问题其实都是瞎耽误工夫;其次,在他们到处找ibatis的问题的时候,注释掉了两行关键代码,后来忘了放回来,所以才发生stored proc修好后,ibatis代码还是不工作,直到换了jdbc才修好。
虽然我解释了原因,同事坚持认为ibatis过于复杂。如果它花了他这么长时间来debug,别人也有可能因为种种原因花很多时间来debug别的问题。
2。ibatis只支持一个参数。这个我也解释了,你可以用java bean或者Map。可是同事认为这也是ibatis的学习曲线问题。如果采用,就要求大家都去学ibatis doc才行。
3。同事原来期待的是象Active Record那样的革命性的提高和简化。象ibatis这样还是要进行手工mapping的,对他来说就是没什么太大意义。他不觉得在java里面做这个mapping有什么不好。(我想,也许Hibernate对他更有吸引力。不过把这个系统转换为Hibernate这工作量可大多了)
4。当我说ibatis可以节省很多资源管理的重复代码时,同事说他可以用PersisterCommand。我说PersisterCommand的这些局限性的时候,他说,他不在乎。大不了直接写jdbc。
5。一致性问题。如果同时用jdbc和ibatis,大家就要学两个东西,造成混淆。而如果要把所有东西都换成ibatis,工作量是一个方面,所有的人都要学习ibatis这个代价也是很大的。
6。同事认为cache的那点重复代码无所谓。即使有一些降低cache hit ratio的bug也不是什么大不了的。
最后无法达成统一意见。因为你说什么优点的时候,他只要一句“我不在乎”你就无话可说了。
在这些论点里面,我也认可ibatis的学习曲线和一致性问题。可是,总不能就永远任由这个持久层代码这么滥下去吧?在java这个领域里,我几乎完全相信不可能出现Active Record等价的东西的。而无论Hibernate还是jpa,只怕都是有不下于ibatis的学习曲线和更高的从遗留系统移植的代价吧?
越来越感觉自己不是一个合格的architect。因为我缺乏说服人的能力。
你怎么看这个问题呢?
评论
17 楼
ajoo
2007-02-07
jkit 写道
光"一致性"就足以枪毙LZ的ibatis了。除非LZ主动义务加班将老系统的模块统统移植到ibatis上去。
自己加班也不成地。我们要求所有代码必须pair,得有人跟我一起自愿加班才行。
何况,自愿加班也解决不了别人要学习ibatis的问题。说实话,ibatis的xml mapping语法还不是十分钟就能搞明白的。
16 楼
jkit
2007-02-06
光"一致性"就足以枪毙LZ的ibatis了。除非LZ主动义务加班将老系统的模块统统移植到ibatis上去。
15 楼
zf_0396
2007-02-06
rollback
和batch 怎么不能用呀
rollback 可以设置手动提交么
batch 有一个方法可以batch
和batch 怎么不能用呀
rollback 可以设置手动提交么
batch 有一个方法可以batch
14 楼
jamesby
2007-02-06
一直用JDBC开发,最近转为使用iBatis,因为我对JDBC的封装相对iBatis来说差太多了!
13 楼
r.zeus
2007-02-06
干吗要学习呢?
楼主把什么都封装好了,他们只要写sql就行了。。
楼主把什么都封装好了,他们只要写sql就行了。。
12 楼
温柔一刀
2007-02-06
要是怕学习曲线高我觉得是没有必要的
一个新手学习ibatis大概最多也就半天吧
而且以后的系统维护工作一般会比jdbc简单很多
一个新手学习ibatis大概最多也就半天吧
而且以后的系统维护工作一般会比jdbc简单很多
11 楼
mingo
2007-02-06
有问题,找领导
10 楼
tangyuanjian2007
2007-02-06
除非用户代码调用openSession(),其它的函数都自动处理了Session的关闭。事务处理用一个boolean参数来控制也相当简单。
能说具体点吗?
能说具体点吗?
9 楼
IvanLi
2007-02-06
我在这里列出里为什么选择ibatis的理由
http://ivanl.iteye.com/blog/24738
http://ivanl.iteye.com/blog/24738
8 楼
jianfeng008cn
2007-02-06
搞技术的人就是这样-固执,所以做技术人员真是难上加难,整天对着的也是这样的人,“将心比心”也许是解决问题的好办法,很多时候技术问题背后藏着别的什么问题呢
7 楼
宏基小键盘
2007-02-06
个人觉得用JDBC不如用Spring的JdbcTemplate
用Spring的JdbcTemplate不如用Spring的SqlMapClientTemplate + iBATIS
不必自己封装,光iBATIS2一个版本已经为java社区服务了三年,还有.net,ruby的版本。
可以自己把框架搭起来,演示一下功能、性能和开发效率。
如果元老连这么一点框架学习的曲线都接受不了或“我不在乎”,那也真老了。
用Spring的JdbcTemplate不如用Spring的SqlMapClientTemplate + iBATIS
不必自己封装,光iBATIS2一个版本已经为java社区服务了三年,还有.net,ruby的版本。
可以自己把框架搭起来,演示一下功能、性能和开发效率。
如果元老连这么一点框架学习的曲线都接受不了或“我不在乎”,那也真老了。
6 楼
Allen
2007-02-06
“使用新工具(新方法)的代价是如此之小,带来的好处却是如此之多!” —— 只有当你你做到令大多数人相信这一点,才能很好的推进自己的“新计划”。
对于legacy builds,推不动看起来“全新”的方法也是正常的,因为它们看起来太不安全可靠了,况且谁都不愿意承认以往的作品存在着“可以大量改进的地方”。
只要是健康运作的公司,就必然会有公司内部的“政治问题”,搞技术的时候也不妨考虑一下自己的建议和观念会对现有的“政治格局”产生怎样的影响……
另外,我必须得说,这种不喜欢用新东西来帮自己擦屁股的态度才是相对而言比较良性的。对比于国内的很多技术人员老喜欢找新东西来替自己过去产品的缺陷遮羞来说,这种态度还是挺有益处的呢。
对于那些对自身撰写JDBC代码能力很有自信的团队而言,通常容易做到“代价小,好处多”的是:
JDBC ---->> commons-DbUtils 而不是 JDBC ---->> iBatis
个人从来没有真正做过构架师(architect),以上言论仅是个人现有见解。
对于legacy builds,推不动看起来“全新”的方法也是正常的,因为它们看起来太不安全可靠了,况且谁都不愿意承认以往的作品存在着“可以大量改进的地方”。
只要是健康运作的公司,就必然会有公司内部的“政治问题”,搞技术的时候也不妨考虑一下自己的建议和观念会对现有的“政治格局”产生怎样的影响……
另外,我必须得说,这种不喜欢用新东西来帮自己擦屁股的态度才是相对而言比较良性的。对比于国内的很多技术人员老喜欢找新东西来替自己过去产品的缺陷遮羞来说,这种态度还是挺有益处的呢。
对于那些对自身撰写JDBC代码能力很有自信的团队而言,通常容易做到“代价小,好处多”的是:
JDBC ---->> commons-DbUtils 而不是 JDBC ---->> iBatis
个人从来没有真正做过构架师(architect),以上言论仅是个人现有见解。
5 楼
jfy3d
2007-02-06
iBatis ,感觉维护管理卡发都快<br/>
学iBatis也就几个小时就基本会用吧 也就比JDBC学习曲线高一点<br/>
<br/>
iBatis 生成map文件花时间多 不过可以自己写个工具自动生成包括formbean<br/>
<br/>
传参数的化 我觉得用formbean比MAP好点
<div class='code_title'>java 代码</div>
<div class='dp-highlighter'>
<div class='bar'> </div>
<ol class='dp-j' start='1'>
<li class='alt'><span><span class='keyword'>public</span><span> </span><span class='keyword'>interface</span><span> BaseDao { </span></span></li>
<li class=''><span> <span class='keyword'>public</span><span> </span><span class='keyword'>int</span><span> insert(Object form); </span></span></li>
<li class='alt'><span> </span></li>
<li class=''><span> <span class='keyword'>public</span><span> </span><span class='keyword'>int</span><span> update(Object form); </span></span></li>
<li class='alt'><span> </span></li>
<li class=''><span> <span class='keyword'>public</span><span> </span><span class='keyword'>int</span><span> delete(Object form); </span></span></li>
<li class='alt'><span> </span></li>
<li class=''><span> <span class='keyword'>public</span><span> Object getInfo(Object form); </span></span></li>
<li class='alt'><span> </span></li>
<li class=''><span> <span class='keyword'>public</span><span> List getList(Object form); </span></span></li>
<li class='alt'><span> </span></li>
<li class=''><span> <span class='keyword'>public</span><span> </span><span class='keyword'>int</span><span> getCount(Object form); </span></span></li>
<li class='alt'><span> </span></li>
<li class=''><span> <span class='keyword'>public</span><span> </span><span class='keyword'>void</span><span> setNamespace(String namespace); </span></span></li>
<li class='alt'><span> </span></li>
<li class=''><span> <span class='keyword'>public</span><span> </span><span class='keyword'>void</span><span> setInsertkey(String insertkey); </span></span></li>
<li class='alt'><span> </span></li>
<li class=''><span> <span class='keyword'>public</span><span> </span><span class='keyword'>void</span><span> setUpdatekey(String updatekey); </span></span></li>
<li class='alt'><span> </span></li>
<li class=''><span> <span class='keyword'>public</span><span> </span><span class='keyword'>void</span><span> setDeletekey(String deletekey); </span></span></li>
<li class='alt'><span> </span></li>
<li class=''><span> <span class='keyword'>public</span><span> </span><span class='keyword'>void</span><span> setListkey(String listkey); </span></span></li>
<li class='alt'><span> </span></li>
<li class=''><span> <span class='keyword'>public</span><span> </span><span class='keyword'>void</span><span> setCountkey(String countkey); </span></span></li>
<li class='alt'><span> </span></li>
<li class=''><span> <span class='keyword'>public</span><span> </span><span class='keyword'>void</span><span> setInfokey(String infokey); </span></span></li>
<li class='alt'><span>} </span></li>
</ol>
</div>
<div class='code_title'>java 代码</div>
<div class='dp-highlighter'>
<div class='bar'> </div>
<ol class='dp-j' start='1'>
<li class='alt'><span><span class='keyword'>public</span><span> </span><span class='keyword'>class</span><span> GeneralDao </span><span class='keyword'>extends</span><span> SqlMapClientDaoSupport </span><span class='keyword'>implements</span><span> BaseDao { </span></span></li>
<li class=''><span> <span class='keyword'>private</span><span> String namespace; </span></span></li>
<li class='alt'><span> <span class='keyword'>private</span><span> String insertkey = </span><span class='string'>"insert"</span><span>; </span></span></li>
<li class=''><span> <span class='keyword'>private</span><span> String updatekey = </span><span class='string'>"update"</span><span>; </span></span></li>
<li class='alt'><span> <span class='keyword'>private</span><span> String deletekey = </span><span class='string'>"delete"</span><span>; </span></span></li>
<li class=''><span> <span class='keyword'>private</span><span> String infokey = </span><span class='string'>"getInfo"</span><span>; </span></span></li>
<li class='alt'><span> <span class='keyword'>private</span><span> String listkey = </span><span class='string'>"getList"</span><span>; </span></span></li>
<li class=''><span> <span class='keyword'>private</span><span> String countkey = </span><span class='string'>"getCount"</span><span>; </span></span></li>
<li class='alt'><span> <span class='keyword'>public</span><span> </span><span class='keyword'>int</span><span> insert(Object form) { </span></span></li>
<li class=''><span> <span class='keyword'>try</span><span> { </span></span></li>
<li class='alt'><span> getSqlMapClientTemplate().insert(namespace+<span class='string'>"."</span><span>+insertkey,form); </span></span></li>
<li class=''><span> <span class='keyword'>return</span><span> </span><span class='number'>1</span><span>; </span></span></li>
<li class='alt'><span> } <span class='keyword'>catch</span><span> (Exception e) { </span></span></li>
<li class=''><span> e.printStackTrace(); <span class='comment'>//To change body of catch statement use File | Settings | File Templates.</span><span> </span></span></li>
<li class='alt'><span> <span class='keyword'>return</span><span> </span><span class='number'>0</span><span>; </span></span></li>
<li class=''><span> } </span></li>
<li class='alt'><span> <span class='comment'>//To change body of implemented methods use File | Settings | File Templates.</span><span> </span></span></li>
<li class=''><span> } </span></li>
<li class='alt'><span> </span></li>
<li class=''><span> <span class='keyword'>public</span><span> </span><span class='keyword'>int</span><span> update(Object form) { </span></span></li>
<li class='alt'><span> <span class='keyword'>return</span><span> getSqlMapClientTemplate().update(namespace+</span><span class='string'>"."</span><span>+updatekey,form); </span><span class='comment'>//To change body of implemented methods use File | Settings | File Templates.</span><span> </span></span></li>
<li class=''><span> } </span></li>
<li class='alt'><span> </span></li>
<li class=''><span> <span class='keyword'>public</span><span> </span><span class='keyword'>int</span><span> delete(Object form) { </span></span></li>
<li class='alt'><span> <span class='keyword'>return</span><span> getSqlMapClientTemplate().delete(namespace+</span><span class='string'>"."</span><span>+deletekey,form); </span><span class='comment'>//To change body of implemented methods use File | Settings | File Templates.</span><span> </span></span></li>
<li class=''><span> } </span></li>
<li class='alt'><span> </span></li>
<li class=''><span> <span class='keyword'>public</span><span> Object getInfo(Object form) { </span></span></li>
<li class='alt'><span> <span class='keyword'>return</span><span> getSqlMapClientTemplate().queryForObject(namespace+</span><span class='string'>"."</span><span>+infokey,form); </span><span class='comment'>//To change body of implemented methods use File | Settings | File Templates.</span><span> </span></span></li>
<li class=''><span> } </span></li>
<li class='alt'><span> </span></li>
<li class=''><span> <span class='keyword'>public</span><span> List getList(Object form) { </span></span></li>
<li class='alt'><span> <span class='keyword'>return</span><span> getSqlMapClientTemplate().queryForList(namespace+</span><span class='string'>"."</span><span>+listkey,form); </span><span class='comment'>//To change body of implemented methods use File | Settings | File Templates.</span><span> </span></span></li>
<li class=''><span> } </span></li>
<li class='alt'><span> </span></li>
<li class=''><span> <span class='keyword'>public</span><span> </span><span class='keyword'>int</span><span> getCount(Object form) { </span></span></li>
<li class='alt'><span> <span class='keyword'>return</span><span> Integer.parseInt(String.valueOf(getSqlMapClientTemplate().queryForObject(namespace+</span><span class='string'>"."</span><span>+countkey, form))); </span></span></li>
<li class=''><span> } </span></li>
<li class='alt'><span> </span></li>
<li class=''><span> <span class='keyword'>public</span><span> </span><span class='keyword'>void</span><span> setNamespace(String namespace) { </span></span></li>
<li class='alt'><span> <span class='keyword'>this</span><span>.namespace = namespace; </span></span></li>
<li class=''><span> } </span></li>
<li class='alt'><span> </span></li>
<li class=''><span> <span class='keyword'>public</span><span> </span><span class='keyword'>void</span><span> setInsertkey(String insertkey) { </span></span></li>
<li class='alt'><span> <span class='keyword'>this</span><span>.insertkey = insertkey; </span></span></li>
<li class=''><span> } </span></li>
<li class='alt'><span> </span></li>
<li class=''><span> <span class='keyword'>public</span><span> </span><span class='keyword'>void</span><span> setUpdatekey(String updatekey) { </span></span></li>
<li class='alt'><span> <span class='keyword'>this</span><span>.updatekey = updatekey; </span></span></li>
<li class=''><span> } </span></li>
<li class='alt'><span> </span></li>
<li class=''><span> <span class='keyword'>public</span><span> </span><span class='keyword'>void</span><span> setDeletekey(String deletekey) { </span></span></li>
<li class='alt'><span> <span class='keyword'>this</span><span>.deletekey = deletekey; </span></span></li>
<li class=''><span> } </span></li>
<li class='alt'><span> </span></li>
<li class=''><span> <span class='keyword'>public</span><span> </span><span class='keyword'>void</span><span> setListkey(String listkey) { </span></span></li>
<li class='alt'><span> <span class='keyword'>this</span><span>.listkey = listkey; </span></span></li>
<li class=''><span> } </span></li>
<li class='alt'><span> </span></li>
<li class=''><span> <span class='keyword'>public</span><span> </span><span class='keyword'>void</span><span> setCountkey(String countkey) { </span></span></li>
<li class='alt'><span> <span class='keyword'>this</span><span>.countkey = countkey; </span></span></li>
<li class=''><span> } </span></li>
<li class='alt'><span> </span></li>
<li class=''><span> <span class='keyword'>public</span><span> </span><span class='keyword'>void</span><span> setInfokey(String infokey) { </span></span></li>
<li class='alt'><span> <span class='keyword'>this</span><span>.infokey = infokey; </span></span></li>
<li class=''><span> } </span></li>
<li class='alt'><span>} </span></li>
</ol>
</div>
目前这样实现的单DAO<br/>
<br/>
学iBatis也就几个小时就基本会用吧 也就比JDBC学习曲线高一点<br/>
<br/>
iBatis 生成map文件花时间多 不过可以自己写个工具自动生成包括formbean<br/>
<br/>
传参数的化 我觉得用formbean比MAP好点
<div class='code_title'>java 代码</div>
<div class='dp-highlighter'>
<div class='bar'> </div>
<ol class='dp-j' start='1'>
<li class='alt'><span><span class='keyword'>public</span><span> </span><span class='keyword'>interface</span><span> BaseDao { </span></span></li>
<li class=''><span> <span class='keyword'>public</span><span> </span><span class='keyword'>int</span><span> insert(Object form); </span></span></li>
<li class='alt'><span> </span></li>
<li class=''><span> <span class='keyword'>public</span><span> </span><span class='keyword'>int</span><span> update(Object form); </span></span></li>
<li class='alt'><span> </span></li>
<li class=''><span> <span class='keyword'>public</span><span> </span><span class='keyword'>int</span><span> delete(Object form); </span></span></li>
<li class='alt'><span> </span></li>
<li class=''><span> <span class='keyword'>public</span><span> Object getInfo(Object form); </span></span></li>
<li class='alt'><span> </span></li>
<li class=''><span> <span class='keyword'>public</span><span> List getList(Object form); </span></span></li>
<li class='alt'><span> </span></li>
<li class=''><span> <span class='keyword'>public</span><span> </span><span class='keyword'>int</span><span> getCount(Object form); </span></span></li>
<li class='alt'><span> </span></li>
<li class=''><span> <span class='keyword'>public</span><span> </span><span class='keyword'>void</span><span> setNamespace(String namespace); </span></span></li>
<li class='alt'><span> </span></li>
<li class=''><span> <span class='keyword'>public</span><span> </span><span class='keyword'>void</span><span> setInsertkey(String insertkey); </span></span></li>
<li class='alt'><span> </span></li>
<li class=''><span> <span class='keyword'>public</span><span> </span><span class='keyword'>void</span><span> setUpdatekey(String updatekey); </span></span></li>
<li class='alt'><span> </span></li>
<li class=''><span> <span class='keyword'>public</span><span> </span><span class='keyword'>void</span><span> setDeletekey(String deletekey); </span></span></li>
<li class='alt'><span> </span></li>
<li class=''><span> <span class='keyword'>public</span><span> </span><span class='keyword'>void</span><span> setListkey(String listkey); </span></span></li>
<li class='alt'><span> </span></li>
<li class=''><span> <span class='keyword'>public</span><span> </span><span class='keyword'>void</span><span> setCountkey(String countkey); </span></span></li>
<li class='alt'><span> </span></li>
<li class=''><span> <span class='keyword'>public</span><span> </span><span class='keyword'>void</span><span> setInfokey(String infokey); </span></span></li>
<li class='alt'><span>} </span></li>
</ol>
</div>
<div class='code_title'>java 代码</div>
<div class='dp-highlighter'>
<div class='bar'> </div>
<ol class='dp-j' start='1'>
<li class='alt'><span><span class='keyword'>public</span><span> </span><span class='keyword'>class</span><span> GeneralDao </span><span class='keyword'>extends</span><span> SqlMapClientDaoSupport </span><span class='keyword'>implements</span><span> BaseDao { </span></span></li>
<li class=''><span> <span class='keyword'>private</span><span> String namespace; </span></span></li>
<li class='alt'><span> <span class='keyword'>private</span><span> String insertkey = </span><span class='string'>"insert"</span><span>; </span></span></li>
<li class=''><span> <span class='keyword'>private</span><span> String updatekey = </span><span class='string'>"update"</span><span>; </span></span></li>
<li class='alt'><span> <span class='keyword'>private</span><span> String deletekey = </span><span class='string'>"delete"</span><span>; </span></span></li>
<li class=''><span> <span class='keyword'>private</span><span> String infokey = </span><span class='string'>"getInfo"</span><span>; </span></span></li>
<li class='alt'><span> <span class='keyword'>private</span><span> String listkey = </span><span class='string'>"getList"</span><span>; </span></span></li>
<li class=''><span> <span class='keyword'>private</span><span> String countkey = </span><span class='string'>"getCount"</span><span>; </span></span></li>
<li class='alt'><span> <span class='keyword'>public</span><span> </span><span class='keyword'>int</span><span> insert(Object form) { </span></span></li>
<li class=''><span> <span class='keyword'>try</span><span> { </span></span></li>
<li class='alt'><span> getSqlMapClientTemplate().insert(namespace+<span class='string'>"."</span><span>+insertkey,form); </span></span></li>
<li class=''><span> <span class='keyword'>return</span><span> </span><span class='number'>1</span><span>; </span></span></li>
<li class='alt'><span> } <span class='keyword'>catch</span><span> (Exception e) { </span></span></li>
<li class=''><span> e.printStackTrace(); <span class='comment'>//To change body of catch statement use File | Settings | File Templates.</span><span> </span></span></li>
<li class='alt'><span> <span class='keyword'>return</span><span> </span><span class='number'>0</span><span>; </span></span></li>
<li class=''><span> } </span></li>
<li class='alt'><span> <span class='comment'>//To change body of implemented methods use File | Settings | File Templates.</span><span> </span></span></li>
<li class=''><span> } </span></li>
<li class='alt'><span> </span></li>
<li class=''><span> <span class='keyword'>public</span><span> </span><span class='keyword'>int</span><span> update(Object form) { </span></span></li>
<li class='alt'><span> <span class='keyword'>return</span><span> getSqlMapClientTemplate().update(namespace+</span><span class='string'>"."</span><span>+updatekey,form); </span><span class='comment'>//To change body of implemented methods use File | Settings | File Templates.</span><span> </span></span></li>
<li class=''><span> } </span></li>
<li class='alt'><span> </span></li>
<li class=''><span> <span class='keyword'>public</span><span> </span><span class='keyword'>int</span><span> delete(Object form) { </span></span></li>
<li class='alt'><span> <span class='keyword'>return</span><span> getSqlMapClientTemplate().delete(namespace+</span><span class='string'>"."</span><span>+deletekey,form); </span><span class='comment'>//To change body of implemented methods use File | Settings | File Templates.</span><span> </span></span></li>
<li class=''><span> } </span></li>
<li class='alt'><span> </span></li>
<li class=''><span> <span class='keyword'>public</span><span> Object getInfo(Object form) { </span></span></li>
<li class='alt'><span> <span class='keyword'>return</span><span> getSqlMapClientTemplate().queryForObject(namespace+</span><span class='string'>"."</span><span>+infokey,form); </span><span class='comment'>//To change body of implemented methods use File | Settings | File Templates.</span><span> </span></span></li>
<li class=''><span> } </span></li>
<li class='alt'><span> </span></li>
<li class=''><span> <span class='keyword'>public</span><span> List getList(Object form) { </span></span></li>
<li class='alt'><span> <span class='keyword'>return</span><span> getSqlMapClientTemplate().queryForList(namespace+</span><span class='string'>"."</span><span>+listkey,form); </span><span class='comment'>//To change body of implemented methods use File | Settings | File Templates.</span><span> </span></span></li>
<li class=''><span> } </span></li>
<li class='alt'><span> </span></li>
<li class=''><span> <span class='keyword'>public</span><span> </span><span class='keyword'>int</span><span> getCount(Object form) { </span></span></li>
<li class='alt'><span> <span class='keyword'>return</span><span> Integer.parseInt(String.valueOf(getSqlMapClientTemplate().queryForObject(namespace+</span><span class='string'>"."</span><span>+countkey, form))); </span></span></li>
<li class=''><span> } </span></li>
<li class='alt'><span> </span></li>
<li class=''><span> <span class='keyword'>public</span><span> </span><span class='keyword'>void</span><span> setNamespace(String namespace) { </span></span></li>
<li class='alt'><span> <span class='keyword'>this</span><span>.namespace = namespace; </span></span></li>
<li class=''><span> } </span></li>
<li class='alt'><span> </span></li>
<li class=''><span> <span class='keyword'>public</span><span> </span><span class='keyword'>void</span><span> setInsertkey(String insertkey) { </span></span></li>
<li class='alt'><span> <span class='keyword'>this</span><span>.insertkey = insertkey; </span></span></li>
<li class=''><span> } </span></li>
<li class='alt'><span> </span></li>
<li class=''><span> <span class='keyword'>public</span><span> </span><span class='keyword'>void</span><span> setUpdatekey(String updatekey) { </span></span></li>
<li class='alt'><span> <span class='keyword'>this</span><span>.updatekey = updatekey; </span></span></li>
<li class=''><span> } </span></li>
<li class='alt'><span> </span></li>
<li class=''><span> <span class='keyword'>public</span><span> </span><span class='keyword'>void</span><span> setDeletekey(String deletekey) { </span></span></li>
<li class='alt'><span> <span class='keyword'>this</span><span>.deletekey = deletekey; </span></span></li>
<li class=''><span> } </span></li>
<li class='alt'><span> </span></li>
<li class=''><span> <span class='keyword'>public</span><span> </span><span class='keyword'>void</span><span> setListkey(String listkey) { </span></span></li>
<li class='alt'><span> <span class='keyword'>this</span><span>.listkey = listkey; </span></span></li>
<li class=''><span> } </span></li>
<li class='alt'><span> </span></li>
<li class=''><span> <span class='keyword'>public</span><span> </span><span class='keyword'>void</span><span> setCountkey(String countkey) { </span></span></li>
<li class='alt'><span> <span class='keyword'>this</span><span>.countkey = countkey; </span></span></li>
<li class=''><span> } </span></li>
<li class='alt'><span> </span></li>
<li class=''><span> <span class='keyword'>public</span><span> </span><span class='keyword'>void</span><span> setInfokey(String infokey) { </span></span></li>
<li class='alt'><span> <span class='keyword'>this</span><span>.infokey = infokey; </span></span></li>
<li class=''><span> } </span></li>
<li class='alt'><span>} </span></li>
</ol>
</div>
目前这样实现的单DAO<br/>
<br/>
4 楼
robbin
2007-02-06
这个不是技术框架的问题,还是人的问题。感觉你的同事很固执。你可以精心准备一次课程,介绍iBTIS引入的效果,做一些对比强烈的例子,预先把他想到的反对理由都准备好相应的反驳策略。
3 楼
giscat
2007-02-06
JDBC封装下,挺好使的
主要的就三把函数 save,update,query
大家都调这么几把函数,协调统一,相当稳健可控
如果不想sql硬编码,那就把他放配置文件
鄙人整的一个综合查询工具,献丑了
http://www.iteye.com/topic/40143
ibatis擅长做复杂查询,insert 与 update 还是hibernate的方式比较帅
可做一个类似hibernate的简易工具,不考虑关联关系(这个是最复杂最难处理的)
ORM变成TOM(table object map)
用TOM来对付insert与update操作,象dynamic save与update都可以轻易的使出来
主要的就三把函数 save,update,query
大家都调这么几把函数,协调统一,相当稳健可控
如果不想sql硬编码,那就把他放配置文件
鄙人整的一个综合查询工具,献丑了
http://www.iteye.com/topic/40143
ibatis擅长做复杂查询,insert 与 update 还是hibernate的方式比较帅
可做一个类似hibernate的简易工具,不考虑关联关系(这个是最复杂最难处理的)
ORM变成TOM(table object map)
用TOM来对付insert与update操作,象dynamic save与update都可以轻易的使出来
2 楼
hgq0011
2007-02-06
楼主你就带头,建好框架,搭建一些iBatis的例子,然后你陪同同事一起使用iBatis,让他们充分感受到iBatis的好。有时间给他们培训一下,学习曲线也怎么难的吧。“1。他和另外一个同事为调试一个使用了ibatis的程序bug花了一天时间。”这个在他们不甚了解iBatis的情况下,肯定会严重排斥iBatis了。当时,如果你在的话,一下子就调试好了,那么他们感觉就会好很多。
1 楼
pojo
2007-02-06
如果简单包装过的JDBC可以解决问题的话,我会选JDBC。理由只有一个:系统设计越简单越好。我做了十几年开发了,见过的各种项目也不少了,真正好的项目都是设计“简单”的项目。
向ajoo和你的同事推销我的DataSet管道技术,见我的《元数据、开放数据模型及动态系统--形而下学篇》,应该比Active Record还要简单。基于JDBC,没有配置,没有子类,完全没有重复代码。
向ajoo和你的同事推销我的DataSet管道技术,见我的《元数据、开放数据模型及动态系统--形而下学篇》,应该比Active Record还要简单。基于JDBC,没有配置,没有子类,完全没有重复代码。
发表评论
-
getThis().getEvilAdvocate().setDead(getTrue())
2008-08-14 04:15 3694code review过程中,看到这样的代码: Pair& ... -
怎样最有效地测试异常?
2008-04-02 21:56 4851工作中,和同事对测试 ... -
DRY与简单性的平衡
2007-02-16 18:45 5594这个事例说起来相当简单。不过小中见大,它大致体现了我和pair ... -
Web AOP?
2007-02-16 11:12 6144今天这个其实不是争论。 这是我接手的一个web系统的一个设计 ... -
依赖是否可以作为一个独立的衡量软件质量的标准?
2007-02-12 05:03 8078这个争论的背景有点复杂。我就尽量简化了说。 遗留系统有一个自 ... -
这样代码重用?
2007-02-12 03:09 19528这是一个工作中遇到的 ... -
一致性和Use Right Tool For Right Job哪个重要?
2007-02-05 12:52 5577这个争执发生在测试的时候。 背景是这样的: 一个接口有很多乱七 ... -
关于 Replace Temp With Query
2007-02-05 11:55 8826这个I disagree系列里面我 ... -
复杂还是不复杂?
2007-02-04 04:01 10426问题是这样的。 一个My ...
相关推荐
本篇文章将深入探讨iBATIS3和JDBC在性能上的对比,以帮助开发者更好地理解这两种技术的优劣。 iBATIS3是一个轻量级的持久层框架,它提供了一种将SQL语句与Java代码分离的方式,通过XML或注解来定义SQL映射,增强了...
标题中的"springmvc_hibernate_ibatis_jdbc"指的是一个整合了SpringMVC、Hibernate、iBatis和JDBC这四种关键技术的Java应用框架。这个框架旨在提供一个全面且强大的解决方案,便于开发人员进行Web应用程序的构建。 ...
### MySQL、JDBC详解及与iBatis对比 #### 一、MySQL基本操作 MySQL作为一款广泛使用的开源关系型数据库管理系统,在IT行业中占有极其重要的地位。对于开发人员来说,掌握MySQL的基本操作至关重要。 ##### 1. 增删...
在源码中,`org.apache.ibatis.transaction.jdbc.JdbcTransaction`和`org.apache.ibatis.transaction.managed.ManagedTransaction`分别对应JDBC和Spring的事务管理。 十、缓存机制 iBatis提供了本地缓存和二级缓存...
iBATIS是一个由Clinton Begin创建,目前由Apache基金会支持的持久化框架,它专注于数据库查询的简化,尤其在JDBC编程方面提供了极大的便利。相对于全自动化ORM解决方案如Hibernate,iBATIS被称为“半自动化”ORM实现...
这里设置事务管理器类型为JDBC,表示ibatis将直接使用底层的JDBC连接进行事务控制,而不是使用Spring提供的事务管理器。 ```xml <transactionManager type="JDBC"> <property value="oracle.jdbc.driver....
Ibatis的出现,解决了传统JDBC中手动编写SQL和结果集映射的繁琐工作,提供了更加灵活的数据访问接口。 在"ibatis demo"中,我们通常会看到以下核心概念和知识点: 1. **配置文件**:Ibatis的配置文件(mybatis-...
相较于传统的 JDBC,Ibatis 提供了更灵活的数据访问层,使得数据库操作更加简洁高效。 二、Ibatis 安装与配置 1. 添加依赖:在 Maven 项目中,需要在 `pom.xml` 文件中添加 Ibatis 的依赖。 2. 配置文件:创建 `...
Ibatis,全称为MyBatis,是一个优秀的Java持久层框架,它主要负责SQL映射,使得开发者能够将注意力集中在编写SQL语句上,而无需关注...因此,无论你是初学者还是有经验的开发者,掌握Ibatis都是提升自己技能的好选择。
"IBATISJDBC包"指的是包含了用于支持IBATIS框架运行所需的JDBC(Java Database Connectivity)驱动及相关依赖的集合。在MYECLIPSE这样的集成开发环境中,这些JAR包是必不可少的,因为它们使得开发者能够无缝地将...
与传统的JDBC相比,Ibatis提供了一种更方便、更易于维护的方式来处理数据库交互。 在使用Ibatis时,首先需要配置数据源,这是通过DataSource接口实现的,常见的实现有Apache的DBCP和C3P0等。接着,我们需要创建...
这样的配置意味着iBatis将使用JDBC的方式进行事务管理,即所有的事务控制逻辑都由iBatis负责,而不是由Spring的事务管理器来处理。 ### 手动控制事务 在实际的应用开发中,如果希望保留iBatis的事务管理机制并能够...
最后,还讨论了iBATIS的优缺点,及为什么是这样的一种方式,即所谓的“在完全OR与JDBC之间的一个幽雅的折衷。” <br>就象Developer's Notebook 系列中所有的书一样,你将由直接的且实用的方式获得信息,这些信息...
### Ibatis3手册知识点概述 Ibatis3作为一款流行的持久层框架,在软件开发领域具有重要的地位。本篇文章基于“Ibatis3手册 Ibatis3参考手册”的标题及描述,深入解析Ibatis3的核心概念、架构特点以及如何进行实际...
iBatis 是一款轻量级的Java持久层框架,它主要负责将数据库操作与业务逻辑解耦,使得开发者可以更加专注于SQL和业务代码的编写。...无论是简单还是复杂的数据库操作,iBatis都能够提供有效的解决方案。
而 iBATIS 是一个持久层框架,它封装了 JDBC,使得 SQL 查询操作更加简洁。 **SpringMVC 知识点** 1. **DispatcherServlet**: SpringMVC 的核心组件,作为前端控制器接收请求并分发到对应的处理器。 2. **Model-...
3. **JDBC驱动设置**: - 在数据库连接时,通过`Connection`对象的`setCharacterEncoding()`方法设置字符集,确保与数据库保持一致。 4. **SQL语句处理**: - 如果在动态SQL中涉及到字符串拼接,务必确保字符串...
4. **连接池**:C3P0 是一个开源的 JDBC 连接池,它实现了数据源和 JNDI 绑定,提供了性能优化功能。在整合中,我们需要配置 C3P0 数据源,以便为应用程序提供高效的数据库连接管理。 5. **配置整合**:在 ...
Ibatis 是一个优秀的开源持久层框架,它允许开发者将 SQL 查询与 Java 代码分离,从而避免了传统的 JDBC 编程中的大量模板代码。作为一个轻量级的框架,Ibatis 提供了灵活的映射机制,使得 XML 或注解方式的 SQL ...
3. SQL Server JDBC驱动:Ibatis通过JDBC与数据库交互,因此需要对应的驱动jar包。对于SQL Server 2005,你需要`sqljdbc4.jar`。 接下来,我们逐步进行环境配置: **1. 创建项目结构** 创建一个新的Java项目,并...