2008-01-29
[原创]Ibatis with MapBean
关键字: ibatis
用了两年的Hibernate之后,对ORM深有感触。一方面,ORM可以令到我们从OO角度来思考数据,屏蔽了数据库的差异(其实 Hibernate被吹的最厉害就是那个分页,其实分页没什么技术含量,而且ROR都把分页从核心抽离了)。另一方面,性能问题,例如必须select才能update,必须select全部,必须update全部,cache带来的后遗症,javabean关联问题(一对多,多对一,多对多等), lazyload问题
Hibernate一直说,他生成的sql比一般程序员的要好,可以减少很多问题。但是,我倒是认为用Hibernate反而因为对程序员的要求更高导致更多问题。而且我现在认为,SQL才是王道,至少目前是。
于是在新项目中启用Ibatis,这一年来的使用感觉很不错,全程使用细粒度的SQL语句,虽然多写了很多SQL语句,但是感觉到项目在自己的控制中
我只用了Ibatis 40%不到的功能,可能大家会觉得不可思议。我没有用cache,没有用关联,没有用resultMap,甚至,连JavaBean也没有用
在大家都在讨论PO,VO,DTO的时候,我的系统里面一个JavaBean都没有
首先我问问,JavaBean是用来做什么的,存储数据,每一个PO,其实就约等于一个表里面的一行数据
我举一个真实一点的例子,一个user表
不知道大家有没有用eclipse生成JavaBean getter/setter的痛苦,至少非常枯燥。整个JavaBean实现了什么功能?完全没有
好了我开谜底了,我用的是HashMap
什么,HashMap?是不是听错了
没听错,请问有什么事情是上面那个那么普通的JavaBean能做到的,而HashMap不能做到的呢
用HashMap没有具体属性的类型啊,那不是变成动态语言一样了,而且我要在JavaBean里面加逻辑怎么办
好吧,这是我想到的两个问题(如果你也有别的问题可以留意提出来)
首先,现在不同以前了,动态语言的优势慢慢提高了,像动态语言有什么不好,我从ROR里面学了很多不错的思想
其次是要加逻辑怎么办,这个问题,之前在Javaeye讨论充血模型还是贫血模型不可开交,最后还是没什么结论,目前还是一片贫血的情况,你可以翻一下你的项目里面的JavaBean,至少大多数的Bean都是没有意义的getter/setter。BO跟PO混杂在一起也很多人不建议的。至于逻辑,大可以写在util包里面,我都把整个model包去掉了,强化一下util不成么,呵呵
再次,数据库的列,跟JavaBean的属性两者,本来就是冗余的,如果我们修改数据库结构,就还要修改相应的JavaBean,或者影射文件。当然我这种做法更依赖数据库。另外,ROR的名字转换功能可以令到代码中的调用名字更好看一些,我觉得也不是非常有必要的实现
直接使用HashMap不太方便,尤其是类型转换上,于是我实现了一个MapBean的类,其实这个类很简单,关键是用HashMap代替JavaBean的思想
这个类主要是方便做类型转换,加入了getInt,getString等方法,另外因为我的系统里面大量使用了JSON,也有一些HashMap向JSON转换的辅助方法,还有一个特别处理过的put方法和构造器,有什么用呢,看下面的例子
MapBean params = new MapBean("id",userId,"name",username,"sex",0,"online",true);
如果你直接用HashMap实现以上功能,要写五行代码,就这个差别而已,呵呵
当然如果你用JavaBean的话,你也可以写一个对应的构造函数
接下来,我们在sql-map-config.xml中加入
就可以用mapbean的别称来引用这个类了
例如具体的SQL xml是这样的
其实我已经把Ibatis当成SQL wrapper来用了,我曾经评估过Spring的JDBC Template,不过功能始终差少少,或许以后我把JDBC Template再强化一下来代替Ibatis吧
http://weavesky.com/2008/01/29/ibatis-with-mapbean/
Hibernate一直说,他生成的sql比一般程序员的要好,可以减少很多问题。但是,我倒是认为用Hibernate反而因为对程序员的要求更高导致更多问题。而且我现在认为,SQL才是王道,至少目前是。
于是在新项目中启用Ibatis,这一年来的使用感觉很不错,全程使用细粒度的SQL语句,虽然多写了很多SQL语句,但是感觉到项目在自己的控制中
我只用了Ibatis 40%不到的功能,可能大家会觉得不可思议。我没有用cache,没有用关联,没有用resultMap,甚至,连JavaBean也没有用
在大家都在讨论PO,VO,DTO的时候,我的系统里面一个JavaBean都没有
首先我问问,JavaBean是用来做什么的,存储数据,每一个PO,其实就约等于一个表里面的一行数据
我举一个真实一点的例子,一个user表
public class User {
private int id;
private String name;
// 省略getter/setter一大段
}
不知道大家有没有用eclipse生成JavaBean getter/setter的痛苦,至少非常枯燥。整个JavaBean实现了什么功能?完全没有
好了我开谜底了,我用的是HashMap
什么,HashMap?是不是听错了
没听错,请问有什么事情是上面那个那么普通的JavaBean能做到的,而HashMap不能做到的呢
用HashMap没有具体属性的类型啊,那不是变成动态语言一样了,而且我要在JavaBean里面加逻辑怎么办
好吧,这是我想到的两个问题(如果你也有别的问题可以留意提出来)
首先,现在不同以前了,动态语言的优势慢慢提高了,像动态语言有什么不好,我从ROR里面学了很多不错的思想
其次是要加逻辑怎么办,这个问题,之前在Javaeye讨论充血模型还是贫血模型不可开交,最后还是没什么结论,目前还是一片贫血的情况,你可以翻一下你的项目里面的JavaBean,至少大多数的Bean都是没有意义的getter/setter。BO跟PO混杂在一起也很多人不建议的。至于逻辑,大可以写在util包里面,我都把整个model包去掉了,强化一下util不成么,呵呵
再次,数据库的列,跟JavaBean的属性两者,本来就是冗余的,如果我们修改数据库结构,就还要修改相应的JavaBean,或者影射文件。当然我这种做法更依赖数据库。另外,ROR的名字转换功能可以令到代码中的调用名字更好看一些,我觉得也不是非常有必要的实现
直接使用HashMap不太方便,尤其是类型转换上,于是我实现了一个MapBean的类,其实这个类很简单,关键是用HashMap代替JavaBean的思想
public class MapBean extends HashMap<String, Object> {
public MapBean() {
}
public MapBean(Object... args) {
put(args);
}
public int getInt(Object key) {
return getInt(key, 0);
}
public int getInt(Object key, int defaultInt) {
Integer i = (Integer) get(key);
return i == null ? defaultInt : i;
}
public String getString(Object key) {
return (String) get(key);
}
public String getString(Object key, String defaultValue) {
String value = (String) get(key);
return value == null ? defaultValue : value;
}
public Timestamp getTimestamp(Object key) {
return (Timestamp) get(key);
}
public void put(Object... args) {
for (int i = 1; i < args.length; i += 2) {
put(String.valueOf(args[i - 1]), args[i]);
}
}
public JSONObject toJson() {
return JSONObject.fromObject(this);
}
public JSONObject toJson(String... keys) {
xxx
}
public String toJsonString() {
return toJson().toString();
}
}
这个类主要是方便做类型转换,加入了getInt,getString等方法,另外因为我的系统里面大量使用了JSON,也有一些HashMap向JSON转换的辅助方法,还有一个特别处理过的put方法和构造器,有什么用呢,看下面的例子
MapBean params = new MapBean("id",userId,"name",username,"sex",0,"online",true);
如果你直接用HashMap实现以上功能,要写五行代码,就这个差别而已,呵呵
当然如果你用JavaBean的话,你也可以写一个对应的构造函数
接下来,我们在sql-map-config.xml中加入
<typeAlias alias="mapbean" type="xxxxxxx.MapBean" />
就可以用mapbean的别称来引用这个类了
例如具体的SQL xml是这样的
<select id="getWorkManagerSystemRole" resultClass="mapbean" parameterClass="mapbean"> select * from work_manager_system_role where system_id=#system_id# and user_id=#user_id# </select>
其实我已经把Ibatis当成SQL wrapper来用了,我曾经评估过Spring的JDBC Template,不过功能始终差少少,或许以后我把JDBC Template再强化一下来代替Ibatis吧
http://weavesky.com/2008/01/29/ibatis-with-mapbean/
评论
罪恶的小手
2008-06-02
我觉得你所说的方法 只是局限于SQL
但是我觉得Hibernate还是为程序员省事了不少,
但是我觉得Hibernate还是为程序员省事了不少,
AllenZhang
2008-04-16
个人觉得楼主的意见是可以参考的。适当用map可以有效地提高开发效率,少诞生一些对象。
基本上就是贫血的pojo用map,带点逻辑或者有点复杂用处的,就建立vo对象吧。
基本上就是贫血的pojo用map,带点逻辑或者有点复杂用处的,就建立vo对象吧。
elice
2008-03-27
确实,使用HashMap可以省很多事,免得写特别多的POJO了
hut
2008-03-09
请教下楼主,如果用map的话,那么再业务逻辑中处理参数的时候怎么办?
直接用 map.get("xxx"); 吗?
那这样的话 直接将"xxx"编码在程序里,合适吗?
直接用 map.get("xxx"); 吗?
那这样的话 直接将"xxx"编码在程序里,合适吗?
leadyu
2008-03-08
鼓捣大家全用Map?不要把Map用滥了,到后面就是个视图字段垃圾桶。看不懂现在评判精华的标准了
rocwon
2008-03-06
hongsoft 写道
楼主用的MapBean就是 我现在用的 SDO的 1/10的功能,不过自己想出来还是比较强的。
我们产品现在也用了这个思路
SDO+HIBERNATE 或者 sdo +iBatis。
应该说,我们的sdo+ibatis比楼主用的功能要强很多。
我现在在 oasis的 SDO标准委员会中,有兴趣可以一起讨论一下 SDO对产品的 架构帮助问题 :)
我们产品现在也用了这个思路
SDO+HIBERNATE 或者 sdo +iBatis。
应该说,我们的sdo+ibatis比楼主用的功能要强很多。
我现在在 oasis的 SDO标准委员会中,有兴趣可以一起讨论一下 SDO对产品的 架构帮助问题 :)
俺曾为JDBC和IBATIS实现过一个EnhancedMap,除了楼主实现的getInt/getString ***以外,还实现了MAP转换为BEAN,BEAN转换为MAP,MAP数据转换为JSON或XML格式; XML,JSON格式数据存入MAP.
lonlyleo
2008-03-05
类似LZ这种方法我也最近也用了,因为最近有些小任务如果照搬正规项目那一堆XO也是个枯燥的活,所以写了一个Util执行简单的查询、更新,List、Map满天飞。查询用了一下ResultSetMetaData,
List<Map<String, Object>> populate(ResultSet rs)
我认为,觉得这样快速有效,应付小项目足够了,还有一定的可配置性。对于具体的规模不大的项目来说,多写两句注释就好了。
不过,在正经的业务系统中我真的是正儿八经的分了很多层,可能是我觉得这样比较节省脑力,简单的业务做起来都像是一个模子出来的,做工人可以按时下班,做程序员可就不一定了,呵呵。
List<Map<String, Object>> populate(ResultSet rs)
我认为,觉得这样快速有效,应付小项目足够了,还有一定的可配置性。对于具体的规模不大的项目来说,多写两句注释就好了。
不过,在正经的业务系统中我真的是正儿八经的分了很多层,可能是我觉得这样比较节省脑力,简单的业务做起来都像是一个模子出来的,做工人可以按时下班,做程序员可就不一定了,呵呵。
hongsoft
2008-03-05
楼主用的MapBean就是 我现在用的 SDO的 1/10的功能,不过自己想出来还是比较强的。
我们产品现在也用了这个思路
SDO+HIBERNATE 或者 sdo +iBatis。
应该说,我们的sdo+ibatis比楼主用的功能要强很多。
我现在在 oasis的 SDO标准委员会中,有兴趣可以一起讨论一下 SDO对产品的 架构帮助问题 :)
我们产品现在也用了这个思路
SDO+HIBERNATE 或者 sdo +iBatis。
应该说,我们的sdo+ibatis比楼主用的功能要强很多。
我现在在 oasis的 SDO标准委员会中,有兴趣可以一起讨论一下 SDO对产品的 架构帮助问题 :)
rocwon
2008-03-05
请问下Insert, Update操作也传递这个MapBean做为参数类吗?
rdsuncn
2008-03-03
hackang 写道
技术本身没有问题,你觉得适合你项目用就行
那种以点盖全的讨论有什么意思,我关心的只是一个问题怎么解决最快、最稳定、客户不会找我麻烦,好让我早点下班
那种以点盖全的讨论有什么意思,我关心的只是一个问题怎么解决最快、最稳定、客户不会找我麻烦,好让我早点下班
赞同
hackang
2008-02-26
技术本身没有问题,你觉得适合你项目用就行
那种以点盖全的讨论有什么意思,我关心的只是一个问题怎么解决最快、最稳定、客户不会找我麻烦,好让我早点下班
那种以点盖全的讨论有什么意思,我关心的只是一个问题怎么解决最快、最稳定、客户不会找我麻烦,好让我早点下班
crazyox
2008-02-25
感觉又变成选择hibernate与ibatis的争论上了。。。
存在即合理, 什么东西都不是绝对的, 楼主这样封装自会有他的道理, 也有可能有自己能派上用场的地方, 用什么都无所谓,根据环境而定, 还是找一个适合自己的吧!
存在即合理, 什么东西都不是绝对的, 楼主这样封装自会有他的道理, 也有可能有自己能派上用场的地方, 用什么都无所谓,根据环境而定, 还是找一个适合自己的吧!
jiakechong
2008-02-24
没用过hibernate,感觉比较复杂, 我还是用ibatis,感觉不错
wq163
2008-02-19
sunwei_07 写道
我现在喜欢使用JdbcTemplate,外加自己封装的FormBean工具,使用也挺顺手
Ibatis我其实很喜欢,但是由于水平有限,实在不知道很好的怎么解决其中的分页方法
Ibatis我其实很喜欢,但是由于水平有限,实在不知道很好的怎么解决其中的分页方法
让Ibatis支持物理分页在这个论坛上有的,实现自己的SqlExecutor ,在获取sqlMap的时候反射进去。不影响其他代码。我在一个项目中就这样用过了,非常好用
那篇主题叫《使ibatis支持hibernate式的物理分页》,现在已经不在了
gumpgz
2008-02-18
maku 写道
引用
我只用了Ibatis 40%不到的功能,可能大家会觉得不可思议。我没有用cache,没有用关联,没有用resultMap,甚至,连JavaBean也没有用
在大家都在讨论PO,VO,DTO的时候,我的系统里面一个JavaBean都没有
...
不知道大家有没有用eclipse生成JavaBean getter/setter的痛苦,至少非常枯燥。整个JavaBean实现了什么功能?完全没有
在大家都在讨论PO,VO,DTO的时候,我的系统里面一个JavaBean都没有
...
不知道大家有没有用eclipse生成JavaBean getter/setter的痛苦,至少非常枯燥。整个JavaBean实现了什么功能?完全没有
在我的项目里大量的使用 resultMap,JavaBean和Map,究竟使用JavaBean还是Map要看具体情况,不能以偏盖全。
eclipse生成JavaBean getter/setter的过程并不痛苦,因为那是工作的一部分;不谈
getter/setter的用处及设计意图,起码他是J2EE规范的一部分,J2EE就是一些约定俗成的规范,你的程序规范,别人阅读和维护起来就容易一些。
感觉楼主似乎厌倦了这些,你可以使用动态语言实现你的想法,但最好别拿java语言开刀。
确实是,现在各种框架、产品都不是万金油,优缺点都很明显。想要一招鲜吃遍天还是有些困难的,关键是怎样扬长避短,总是争论某几个产品的孰优孰劣也没有实际意义。
1、完全抛弃javabean也不一定是好事,面向对象的思想提出不是一天两天了,还是经得起考研的。当然,全用map也未尝不可,早期我们的项目也是这种做法。
2、javabean的生成也不是复杂的事情,hibernate、ibatis都提供了javabean的生成方法和插件,都符合javabean的标准定义,基本可以通用,再不济自己可以写一套javabean生成方法,建库完了生成就是了。
3、至于分页,ibatis的分页已经不推荐使用。我自己仿照hibernate的做法,利用数据库的特性,做了个分页程序,适用于oracle、db2、sql server2005、mysql,因为这些数据库都提供了rownum(直接或者间接)这个保留字。下一步打算融合到ibatis中。
4、ibatis不适合移植,这个确实是问题。我在ibm开发专区看到过有人写的实现方案,是每种数据库都写一个map文件,可以自动判断数据库类型读取文件。后来,我想了一下,有个变通的做法,可以在map文件对特殊sql(不具有移植性的)针对每种数据库都写一套,然后命名成不同的名字,如"queryUserList"、"queryUserList#db2"、"queryUserList#oracle"累死这种,修改ibatis的加载机制,根据数据库类型不同自动读取对应的sql信息,这样能减少map配置文件,也便于维护。此修改也正在实施中。
个人观点,欢迎讨论
yyjn12
2008-02-18
1314520ln 写道
看来你还没真正了解hibernate
你了解那就请你说说
96sd2
2008-02-16
这种思路的确值得借鉴
xfan1982
2008-02-15
我就是用map搞定一切
rtm
2008-02-15
HashMap代替JavaBean的唯一缺点就是没有类型安全,HashMap满天飞.
受限于静态语言,这个是没有办法的.
如果是动态语言来实现Hibernate或者Ibatis,我相信会更加的灵活.比如分页,用Oracle的rownum分页,需要计算firstrow,lastrow,现在迫不得已只能让参数类继承一个Page类,里面有firstrow,lastrow两个字段,如果是动态语言,多爽啊,动态加上两个字段,用完了删除,外面的参数类干干净净
受限于静态语言,这个是没有办法的.
如果是动态语言来实现Hibernate或者Ibatis,我相信会更加的灵活.比如分页,用Oracle的rownum分页,需要计算firstrow,lastrow,现在迫不得已只能让参数类继承一个Page类,里面有firstrow,lastrow两个字段,如果是动态语言,多爽啊,动态加上两个字段,用完了删除,外面的参数类干干净净
yao_2110
2008-02-15
leebai 写道
基本赞成楼主的观点,OR Maping是典型的穷折腾。
加个前提,再不需要可移植性的情况下。。。
多数情况不需要可移植性,大家关注的都是性能。。。这个时候用hibernate是自找麻烦,不是hibernate做得不好。。。
发表评论
提醒: 该博客已发表在公共论坛,博客所有留言会成为论坛回贴,留言请注意遵守论坛发贴规则
- 浏览: 645 次
- 性别:

- 来自: 广州

- 详细资料
搜索本博客
最近加入圈子
最新评论
-
[原创]sexy Quartz
不明白为什么做定时器一定要生成一个job.用这个job有什么用? 我的做法是1: ...
-- by dmewy -
[原创]sexy Quartz
bluemeteor 写道如果项目中使用,建议使用数据库的JOB+SP来实现数据 ...
-- by tidus2005 -
[原创]Ibatis with MapBe ...
我觉得你所说的方法 只是局限于SQL 但是我觉得Hibernate还是为程序员 ...
-- by 罪恶的小手 -
[原创]Ibatis with MapBe ...
个人觉得楼主的意见是可以参考的。适当用map可以有效地提高开发效率,少诞生一些对 ...
-- by AllenZhang -
[原创]Ibatis with MapBe ...
确实,使用HashMap可以省很多事,免得写特别多的POJO了
-- by elice






评论排行榜