- 我是一个线程(修订版)
- 我是一个 Java class
- Javascript:一个屌丝的逆袭
- Java : 一个帝国的诞生
- JSP 一个装配工的没落
- TCP/IP 之 大明王朝邮差
- TCP/IP 之大明内阁
- TCP/IP 之蓟辽督师
- CPU 阿甘
- CPU 阿甘之烦恼
- CPU 阿甘:函数调用的秘密
- 我是一个网卡
- 我是一个路由器
- 我是一个进程
- 我是一块硬盘(上)
- 我是一块硬盘(下)
- 我是一个键盘
- 张大胖的 socket
- 张大胖学递归
- 学习面向对象的令狐冲
- 张大胖学数据库
- 数据库村的旺财和小强
- 小李的数据库之旅(上)
- 小李的数据库之旅(下)
- 漫画:什么是机器学习?
- 那些烦人的同步和互斥问题
- IE 为什么把火狐和 Chrome 给打伤了?
- 对浏览器村的第二次采访
- 节约标兵 IE 的自述
- EMail 诞生记
- Email 诞生记(下)
- Http 历险记(上)
- Http 历险记(下)-- Struts 的秘密
- 动物王国的面向对象
- 冯·诺伊曼计算机的诞生
- Http Server : 一个差生的逆袭
- 张大胖的加法器
- 从 1 加到 100:一道简单的数学题挑战下你的大脑
- 编程语言
- Javascript:一个屌丝的逆袭
- 计算机语言之战
- 我和编程语言的爱恨情仇(上)
- 我和编程语言的爱恨情仇(下)
- Android 为什么选择了 Java
- iOS 为什么选择了 Object-C?
- Basic : 一个老兵的自述
- Node.js : 我只需要一个店小二
- 命令式编程 vs 声明式编程
- 编译还是解释?
- 程序人生
- “架构师"小赵
- 师兄说
- 师姐说
- 小王的架构师之路
- 小李的版本管理系统
- 小超穿越记
- 小李的 Build 之路(上)
- 小李的 Build 之路(下)
- 张大胖改 Bug
- 我的编程之路--大学趣事
- 码农小王的一天
- 小李在外企
- 张大胖的需求估算
- 从厨师到码农
- 聊一聊那些神一样的程序员们(上)
- 聊一聊那些神一样的程序员们(中)
- 聊一聊那些神一样的程序员们(下)
- 谁是互联网之父?
- 一个价值百万的创业教训
- 让自己与众不同 - 提升工作的价值
- 看看你的“易燃性”
- 从无聊的工作中寻找价值
- 什么样的学生适合报考计算机?
- 谈谈程序员的职业方向(上)
- 谈谈程序员的职业方向(中)
- 谈谈程序员的职业方向(下)
- 谈谈培训班的作用
- 码农需要知道的“潜规则”
- 学习编程的加速度
- 码农在工作中的必备能力
- 码农和英语
- 老司机经验
- 假如时光能够倒流, 我会这么学习 Java
- 假如我是计算机系老师
- 学会编程, 而不是学会 Java
- 从增删改查中突围
- 抽象:程序员必备的能力
- 懒就一个字
- 编程的自学方法
- 小王买房记
- 从一道面试题谈谈一线码农应该具备的基本素质
- 想写框架的看过来
- 苹果手机变砖头以后
- 如何快速的学习一门技术?
- 唯一不变的是变化: 谈谈微信应用号
- 什么是企业应用?
- 勿以浮沙筑高台
- 为什么敏捷开发难于成功?
- localhost vs 127.0.0.1
- GitHub/Stackoverflow 找工作时有什么用?
- 动词 or 名词 :这是一个问题
- 如何选择入行语言
- 有时候,沉默是金
- 零 Bug 的代码是怎么炼成的?
- 浮点数为什么不精确?
- 文章错误大全
- Open Source--不要为了开源而开源
- 一不留神,代码就腐化了
- 先做个“键盘侠”, 再来写程序
- 不加断点调试的程序员是好程序员
- 码农必备技能:烂代码的处理之道(上)
- 码农必备技能:烂代码的处理之道(下)
- 学习数据结构有用吗?
- 从现在开始,丰富你的简历
- 那些永不过时的书,你看过几本吗?
- 学好编程必备的一个品质你知道吗?
- 你最爱的 Java
- 搞懂了这几点,你就学会了 Web 编程
- Spring 的本质系列(1) -- 依赖注入
- Spring 本质系列(2)-AOP
- 三层架构和 MVC 那点事儿
- Java 帝国之拨云见日识回调
- 小张的 Duck Typing
- JDBC 的诞生
- JDBC 后传
- 一个不安分的 JDBC 驱动
- Java 帝国之 Java bean (上)
- Java 帝国之 Java bean(下)
- Java 帝国之函数式编程
- Java 帝国之函数式编程(下)
- 关于 Java 初学者需要知道的 10 件事
- JUnit 你不知道的那些事儿
- 圣诞礼物:Java EE 的历史
- Java EE 读书指南
- 给小白的 Java EE 指南
- 给小白的 Java EE 指南(2)
- 给小白的 Java EE 生存指南(3) : XML
- 给小白的 Java EE 生存指南(4) : 一只叫 Tom 的猫
- 给小白的 Java EE 指南(5) : AJAX
- 给小白的 Java EE 生存指南(6) :Java 反射
- 闲聊
- "饿了么"初体验
- 来自大脑的控诉
- 一个高中生是怎么玩自媒体的?
- 尝试 分答
- 到底应不应该上培训班?
- 自学编程中遇到问题怎么办?
- 据说 99%的初级程序员看完后都不迷茫了
- 一行代码引发的“血案”
- 对一个死锁问题的思考
- 通过外包进入名企
- 请开往十年前的今天
- 为什么自学中最好有个师傅指导一下?
- 这个网站值得你花时间投入
- 为什么你无法坚持自学编程?
JDBC 后传
抱怨
JDBC 出现以后, 以其对数据库访问出色的抽象, 良好的封装, 特别是把接口和具体分开的做法, 赢得了一片称赞。
乘着 Java 和互联网的东风, JDBC 在风口飞了起来, 无数的程序开始使用 JDBC 进行编程, 访问数据库村的数据库, 在数据库村,无论是大佬 Oracle, 还是小弟 Mysql 都赚的盆满钵满。
所谓物极必反, JDBC 的代码写得多了, 它的弱点就暴露出来了, 很多码农抱怨道:“JDBC 是在是太 Low 了”。
消息传到 Tomcat 村, Java 简直不相信自己的耳朵: “什么? JDBC 还很 low ? 看来那帮码农没有用 socket 访问过数据库吧?! 那才叫 low . ”
Tomcat 说 : “你是个标准的制定者, 写代码太少了,太不接地气了, 你看看这样的代码: ”
Java 把代码拿过来一看, 不由的倒吸了一口凉气: “ 代码怎么这么长啊, 似乎是有那么一点问题, ‘ 噪声 ’似乎太多了, 把业务代码全给淹没了”
Tomcat 说:”看来你也是个明白人啊, 为了正确的打开和关闭你定义的 Connection , Statement, ResultSet 需要花很多功夫, 再加上那些异常处理, 一个 50 多行的程序, 真正做事的也就那么 10 几行而已, 这些琐碎代码太烦人了, 所以大家抱怨很 low 啊。 ”
Java 表示同意: “不错, 可以想象, 如果代码中有大量这样的代码, 码农会抓狂的, 不过,” Java 突然想到了些什么 , “其实这不是我的问题, 码农们抱怨错人了, 我作为一门语言, 所能提供的就是贴近底层(socket) 的抽象, 这样通用性最强。 至于码农想消除这些重复代码, 完全可以再封装, 再抽象, 再分层啊 ”
Tomcat 想想也是, 在计算机世界里, 每个人都有分工, 不能强求别人做不喜欢也不擅长的事情, 看来这件事错怪 Java 了。
JDBCTemplate
Java 预料的不错, 稍微有点追求, 不愿意写重复代码的码农都对 JDBC 做了封装, 例如写个 DBUtil 的工具类把打开数据库连接, 发出查询语句都封装了起来。
码农的抱怨也渐渐平息了。
有一天, 有个叫 JDBCTemplate 的人来到了 Tomcat 村找到了 Java , 他自称是 Rod Johnson 派来专门用于解决 JDBC 问题的, 他提供了一个优雅而简洁的解决方案。
(注: Rod Johnson 就是 Spring 最初的作者)
JDBCTemplate 说: “尊敬的 Java 先生, 感谢您发明了 JDBC, 让我们可以远程访问数据库村, 您也听说了不少对 JDBC 的抱怨吧, 我的主人 Rod Johnson 也抱怨过, 不过他在大量的编程实践中总结了很多经验, 他认为数据库访问无外乎这几件事情:
指定数据库连接参数
打开数据库连接
声明 SQL 语句
预编译并执行 SQL 语句
遍历查询结果
处理每一次遍历操作
处理抛出的任何异常
处理事务
关闭数据库连接”
“我的主人认为” JDBCTemplate 说, “开发人员只需要完成黑体字工作就可以了,剩下的事情由我来办“
“你们主人的总结能力很强, 把一个框架应该做的事情和用户应该做的事情区分开了 ” Java 说
JDBCTemplate 看到 Java 态度不错, 赶紧趁热打铁: “ 我给你看个例子:”
Java 和之前那个传统的 JDBC 比较了一下, JDBCTemplate 的方式的确是把注意力放到了业务层面: 只关注 SQL 查询, 以及把 ResultSet 和 User 业务类进行映射, 至于如何打开/关闭 Connection, 如何发出查询,JDBCTemplate 在背后都给你悄悄的完成了, 完全不用码农去操心。
“你在 JDBC 上做了不错的抽象和封装” Java 说, “但是我还不明白 JDBCTemplate 怎么创建出来的”
“这很简单, 你可以直接把它 new 出来, 当然 new 出来的时候需要一个参数, 就是 javax.sql. DataSource, 这也是你定义的一个标准接口啊”
"当然, 我主人 Rod Johnson 推荐结合 Spring 来使用, 可以轻松的把我‘注入’到各个你需要的地方去"。
“明白了, 你们主人这是要推销 Spring 啊, 那是什么东西? ”
“简单的说,就是一个依赖注入和 AOP 框架, 功能强大又灵活。 具体的细节还得让我主人亲自来给您介绍了 ”
“好吧, 不管如何, 我看你用起来还不错, 可以向大家推荐一下。”
O/R Mapping
JDBCTemplate 这样对 JDBC 的封装 , 把数据库的访问向前推进了一大步, 但是 Tomcat 村和数据库村的很多有识之士都意识到: 本质的问题仍然没有解决!
这个问题就是面向对象世界和关系数据世界之间存在的巨大鸿沟。
Tomcat 村的 Java 程序都是面向对象的: 封装、继承、多态, 对象被创建起来以后, 互相关联, 在内存中形成了一张图。
数据库村的关系数据库则是表格: 主键,外键, 关系运算、范式、事务。 数据被持久化在硬盘上。
ResultSet 依然是对一个表的数据的抽象和模拟: rs.next() 获取下一行, rs.getXXX("XX") 访问该行某一列。
把关系数据转化成 Java 对象的过程, 仍然需要码农们写大量代码来完成。
现在码农的呼声越来越高, 要把这个过程给自动化了。 他们的要求很清晰: 我们只想用面向对象的方式来编程, 我们告诉你 Java 类、属性 和数据库表、字段之间的关系, 你能不能自动的把对数据库的增删改查给实现了 ?
他们还把这个诉求起了一个很洋气的名称: O/R Mapping (Object Relational Mapping)
Java 自然不敢怠慢, 赶紧召集 Tomcat 村和数据库村开了一次会议, 确定了这么几个原则:
1. 数据库的表映射为 Java 的类(class)
2. 表中的行记录映射为一个个 Java 对象
3. 表中的列映射为 Java 对象的属性。
但是光有这几个原则是远远不够的, 一旦涉及到实际编程, 细节会扑面而来:
1. Java 类的粒度要精细的多, 有时候多个类合在一起才能映射到一张表
例如下面的例子, User 类 的 name 属性其实是也是一个类, 但在数据库 User 表中, firstName, middleName, lastName 却是在同一张表中的。
2. Java 的面向对象有继承, 而数据库都是关系数据, 根本没有继承这回事!
这时候可选的策略就很多了, 比如
(1) 把父类和子类分别映射到各自的 Table 中, 数据会出现冗余
(2) 把父类的公共属性放到一个 Table 中, 每个子类都映射到各自的 Table 中, 但是只存放子类自己的属性。子类和父类的表之间需要关联。
(3) 干脆把父类和子类都映射到同一张 Table 中, 用一个字段(例如 Type)来表明这一行记录是什么类型。
3. 对象的标识问题
Java 中使用 a==b 或者 a.equals(b) 来进行对象是否相等的判断, 而数据库则是另外一套:使用主键。
4. 对象的关联问题
在 Java 中, 一个对象关联到另外一个或者一组对象是在是太常见了, 双向的关联(也就是 A 引用 B , B 反过来也引用了 A )也时常出现, 而在数据库中定义关联能用的手段只剩下外键和关联表了。
5. 数据导航
在 OOP 中, 多个对象组成了一张网, 顺着网络上的路径, 可以轻松的从一个对象到达另外一个对象。 例如: City c = user.getAddress().getCity();
在关系数据库中非得通过 SQL 查询, 表的连接等方式来实现不可。
6. 对象的状态
在 OOP 中, 对象无非就是创建出来使用, 如果不用了,就需要回收掉, 但是一旦扯上数据库, 势必要在编程中引入新的状态,例如“已经持久化”
......
(注: 本来想讲 Hibernate, 但是限于篇幅, 实在是无法展开讲细节, 这几个问题是 Hibernate 官网上提到的, 是 O/R Maping 的本质问题)
这些细节问题让 Java 头大, 他暗自思忖: " 还是别管那些码农的抱怨, 我还是守住 JDBC 这一亩三分地吧, 这些烦人的 O/R Mapping 问题还是让别人去处理好了。 "
O/R Mapping 的具体实现就这么被 Java 搁置下了。
Hibernate 和 JPA
随着时间的推移,各大厂商都想利用 Java 赚钱, 联合起来搞了一个叫 J2EE 的规范, 然后疯狂的推行自己的应用服务器(例如 Weblogic, Websphere 等等),还搭配着硬件销售, 在互联网泡沫时代赚了不少钱。
J2EE 中也有一个叫 Entity Bean 的东西, 试图去搞定 O/R Mapping , 但其蹩脚的实现方式被码农们骂了个狗血喷头。
转眼间, 时间到了 2001 年, Tomcat 告诉 Java 说: “听说了吗? 现在很多码农都被一个叫 Hibernate 的东西给迷住了”
"冬眠(Hibernate) ? 让内存中的数据在数据库里冬眠, 这个名字起的很有意境啊 , 我猜是一个 O/R Mapping 工具吧"
"没错, 是由一个叫 Gavin King 的小帅哥开发的, 这个框架很强悍, 它实现了我们之前讨论的各种烦人细节, 大家都趋之若鹜, 已经成为 O/R Mapping 事实上的标准, Entity Bean 已经快被大家抛弃了。 "
“没关系, Entity Bean 从 1.0 开始就是一个扶不起的阿斗, 我已经想通了, 我这里只是指定标准, 具体的实现让别人去做。 既然 Hibernate 这么火爆, 我们就把 Gavin King 招安了吧 ”
“怎么招安? ”
“让小帅哥过来领导着大家搞一个规范吧, 参考一下 Hibernate 的成功经验 , 他应该会很乐意的。 ”
不久以后, 一个新的 Java 规范诞生了, 专门用于处理 Java 对象的持久化问题, 这个新的规范就是 JPA(Java Persistence API), Hibernate 自然也实现了这个规范, 几乎就是 JPA 的首选了。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论