查看原文
其他

持久化:Java帝国反击战

2017-07-31 老刘 码农翻身
1  断电的威胁


强大的Java帝国自成立一来, 一直顺风顺水, 可是外人不知道的是,帝国也有个致命的弱点, 那就是害怕一种叫做“断电”的攻击。


每次攻击来临, 帝国辛辛苦苦制造出Java对象都会瞬间死亡, 变成孤魂野鬼,在电脑里四处游荡,最终悄无声息地消失在空气中。


这是没有办法的事情, 帝国生存所依仗的Java对象都必须在内存中才能工作, 而内存最怕“断电” !


这件事情变成了国王的一件心病,茶不思饭不想。


某日朝会, 国王又把这个难题抛给了下面战战兢兢的各位大臣。


线程大臣说: “大王, 我们能不能跳过内存,直接使用硬盘来操作Java对象?”


IO大臣最近压力最大,已经好几天没合眼了:“不懂别瞎BB,你知道硬盘有多慢吗,比内存慢几万甚至10几万倍, 用硬盘怎么干活?还有人类的冯诺依曼体系要求了,数据必须在内存中CPU才能操作。 ”


线程大臣脑洞打开:“要是发明一个硬盘,容量无限大,速度和CPU一样,那CPU不就直接操作硬盘了,还要内存干什么?!”


国王叹了口气: “别吵了,谁要是发明一个这样的硬盘,我会授予他100次Java帝国诺贝尔奖!  你们知道人类的摩尔定律吗?集成电路上的晶体管每隔18个月便会增加一倍, 性能也会提升一倍。可是这硬盘不行啊, 就像手机上的电池一样,一直以来都像老牛拉破车,慢慢吞吞地在发展,这么多年都没有重大的突破。”


IO大臣说:“ 大王不用灰心, 臣最近想出了一个办法,叫做序列化, 可以把内存中那些重要的对象转化为二进制文件存储到硬盘上,这样就不怕断电了”


“等到电力恢复以后,还能再让他们回到内存吗?”


“那是自然, 我们可以反序列化,把二进制文件变成Java对象,继续在内存中干活。”


国王大喜,颁布命令,要求臣民们都必须学会IO大臣发明的序列化。

2  数据库联合酋长国 45 33851 45 15265 0 0 2959 0 0:00:11 0:00:05 0:00:06 2960


序列化虽然解决了一部分问题, 但是臣民们很快发现了它的弱点: 效率低。


Java对象少的时候还行,如果需要大规模地对Java对象进行存储、查询的时候那几乎不能用。 比如说想选取 age > 28的所有Person对象, 那就得把所有序列化的Person 对象都装入内存, 一个个的比较年龄, 这实在是太费劲了。


IO大臣这次也辙了, 只好建议国王去国外考察,看看人家遇到这个问题是怎么解决的。


国王放下高傲的身段, 派出了多个使团,分别出访了C++,  Python, Ruby, C#... 等王国。


一个月后,使团陆续返回,带回的消息惊人得一致:  使用关系数据库存储大规模数据。


“关系数据库? ”  国王听说过这个东西,在Java帝国东边的大海上,有一个叫做数据库的岛屿,那里有几个很大的部落,好像有什么Oracle,  Db2, SQLServer ,MySql 之类, 他们组成了一个联合酋长国。


IO大臣说: “关系数据库就是用类似二维表格的方式来存储数据,臣听说他们从70年代末开始就开始发展, 由于有强大的理论基础,像什么关系代数,关系演算, 现在发展的非常成熟,可以进行大规模的数据存储和查询,还可以支持我们梦寐以求的事务操作呢。 奥对了,他们搞出了一个叫SQL的东西,屏蔽了具体的实现细节和各个数据库之间的差异。”


线程大臣还在记恨IO大臣一个月前的讽刺,马上柔中带刚,皮笑肉不笑地甩出一个炸弹: “这个酋长国看起来挺好啊, 只是IO大臣提到他们用二维表格的方式来存储数据, 而我们这里是Java对象,好像不太匹配啊。”


国王上钩,向IO大臣发难: “ 一个是表格的行和列,一个是对象的属性, 我们怎么把对象存储到表格中?”


IO大臣胸有成竹地说: “这需要我们的臣民自己写代码,把对象属性变成数据库的行/列, 人家别的王国都是这么干的, 这种办法还有一个很好听的名称叫Object-Relational Mapping, 只是现在这种Mapping 需要我们手工来做罢了,  你要想大规模的查询和存储数据,总不能一点代价都不付出吧。 ”


国王说: "那就这么办吧, IO大臣,你去负责和数据库联合酋长国谈判,让他们和我们Java帝国协调一个接口出来,名称就叫......"


IO大臣马上接口: “Java Database Connectivity ,简称JDBC,如何?”


“好! 就用这个名称, 你去谈判一定要坚守住帝国的底线, 那就是我们只负责定义接口, 具体的JDBC实现必须由各个数据库去提供!   你要是搞不定,就别回来见我。 退朝!”


3  表面风光的EJB


半年以后,Java帝国和数据库联合酋长国就JDBC达成一致,双方签署了正式的协议, 帝国的臣民们欢欣鼓舞, 纷纷开始使用JDBC作为持久化的工具。


可是这JDBC的劣势也很明显: 这是一个非常“低级”的接口, 程序员需要处理太多的细节, 冗余代码太多,写个简单的查询就得一大堆代码伺候,打开connection,创建statement, 执行sql, 遍历resultset, 还得记住关闭connection,要不然会资源泄露......


此时Java帝国正准备向企业级应用进军,  需要支持安全,事务,分布式、可伸缩性,高可用性.....等高级功能, 这些脏活累活操作系统不想做, 应用程序也不想干,那到底扔给谁呢?


帝国一合计,提出了一个令人耳目一新的概念: 中间件(middleware )  , 专门负责底层操作系统和上层应用程序都不愿意做的事情。


帝国充分发挥了制定标准的特长, 搞了一套J2EE的规范出来,其中包罗万象,涵盖了大部分企业开发的需求, 把通用的,复杂的服务交给中间件提供商去搞定, 让开发人员集中在业务逻辑的开发上。


这其中有个标准就是EJB, 帝国大肆宣传: 只要使用了EJB, 再也不用写那些烦人的JDBC代码了,数据的创建,读取,甚至查询都可以用面向对象的风格搞定。 更牛的是这些EJB实例可以在一个集群上分布式运行。


在Websphere, Weblogic, Jboss等应用服务器的支持和鼓噪下,J2EE在初期热度非凡, 帝国横扫企业级市场,别的王国只有看热闹的份。


Java帝国的臣民们享受着外界羡慕的目光,骄傲地使用EJB进行开发,然后扔到应用服务器中执行。


但是其中的辛苦和委屈只有自己知道: 开发繁琐,难于测试,性能低下,除了表面的风光,已经剩不下什么了。


4  轻量级O/R Mapping框架


2001年,帝国有个叫Gavin King的,终于无法忍受金玉其外败絮其中的EJB,  自己偷偷另起炉灶,搞了一个O/R Mapping的框架出来, 名称很有意思,叫做Hibernate。  


冬眠? 好像到了冬天让内存的数据进入数据库冬眠,  春天来了从冬眠中醒来,再次进入内存工作。


Gavin宣称使用Hibernate ,你可以把Java 的属性用声明的方式映射到数据库表, 完全不用你操心connection, sql 这些细节。


帝国刚开始没在意,觉得这就是个玩具,哪能和强大的EJB相比?  


好东西永远都不缺市场,一传十、十传百,Hibernate很快成了气候, 使用简单、灵活,特别是脱离了那些庞大,昂贵的Websphere, weblogic容器也能使用。 一下子捕获了很多臣民的心。


同年另外一个叫做iBatis的O/R Mapping框架也出现了, 又拉走了一大批EJB臣民。


2004年 Rod Johnson 给了EJB以致命一击, 他写了一本《Expert One-on-One J2EE Development without EJB 》 , 公然宣扬不使用EJB, 而要使用更加轻量级的框架,也就是他鼓捣出的Spring。


帝国宣称这是一本禁书,禁止出版发行。可是人的意志总是挡不住历史的潮流, 抛弃重量级的EJB, 使用更加轻量级的Spring成了大势所趋。


这个Spring 不但自己提供了轻量级的访问数据库的方法JDBCTemplate, 还能轻松的集成Hibernate, iBatis 等一批工具。慢慢的竟然成为了事实的标准, 在帝国流行开来。


5 帝国的反击


在一次早朝上IO大臣简直是气急败坏了:“陛下,再不禁止Spring ,Hibernate ,iBatis的使用, 我们的EJB就要被抛弃了。”


国王说: “你禁止得了吗,上次你禁止Rod的那本书,民间的小抄还不是疯狂流行?  最近的起义风起云涌,按下葫芦浮起瓢,扑灭了这个,那个又起来了。倒不如任他们去,毕竟也大大地繁荣了我们Java帝国啊”


线程大臣立刻拍马屁: “陛下的心胸真是如同大海般广阔,不过臣倒有一计, 既然官方EJB标准抵不过Hibernate的事实标准, 我们要不就把Gavin King 招安了算了,为我所用。”


国王表示赞同,命令线程大臣负责招安以及后续工作。


Gavin 之前已经加入JBoss部落,现在代表JBoss正式进入JCP,也算是被招安了。 他早就有改造官方标准的雄心壮志, 带领着帝国的EJB团队推出了EJB3.0 , 成功地向Hibernate 看齐, 其中有些注解简直一模一样,极大的简化了开发。   各大厂商重新开始摇旗呐喊,为EJB3.0站台背书。


只是这个EJB3.0有个致命缺陷: 没法离开容器(Websphere, weblogic ,JBoss等)运行,  臣民们已经适应了轻量级开发, 已经抛弃了重量级的应用服务器,在Spring 的带领下,他们再也不需要一个容器来运行EJB了,   帝国的这次声势浩大的反击战被化于无形。


不过在EJB3.0中悄悄埋下了一个副产品,叫做Java Persistence API(JPA), 充分地反应了帝国的小算盘, 既然我在实现层面无法打败你们,那我就制定我最擅长的标准, 用标准整合O/R Mapping,  一统天下, 唯我独尊!


在帝国的力推之下, Hibernate , EclipseLink ,OpenJPA等知名产品都提供了针对JPA的实现, 可是帝国的官员们悲哀地发现: 现在臣民们又爱上了写SQL语句的MyBatis,   唉,这民意真是难以琢磨啊。


国王最终决定改换策略,无为而治,放下官方的架子,只要是有利于帝国的,不再阻碍, 任其发展,趁机招安。


帝国反击战就此落幕,持久化工具之战以民间的最终胜利告终。



(完)


相关文章:

小李的数据库之旅 -- 数据库最基本原理

小李的数据库之旅(下)

JDBC的诞生

一个不安分的JDBC驱动--数据库连接池的故事

张大胖学数据库--范式的故事

数据库村的旺财和小王--数据库隔离级别的故事

序列化:一个老家伙的咸鱼翻身


你看到的只是冰山一角, 更多精彩文章,请移步《码农翻身2016文章精华》或者《码农翻身2017上半年文章精华


有心得想和大家分享? 欢迎投稿 ! 我的联系方式:微信:liuxinlehan  QQ: 3340792577


码农翻身

用故事讲述技术

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存