持久化:Java帝国反击战

时间:2021-07-02 03:50:19

1

  断电的威胁

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

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

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

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

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

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

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

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

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

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

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

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

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

  2

  数据库联合酋长国

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

  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, 唉,这民意真是难以琢磨啊。

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

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

  (完)