[转载]JDO之前世今生
1 Java与数据库应用,JDBC
Java发明以来,在短短的几年之间,迅速占领了从桌面应用(J2SE)到服务器 (J2EE),再到小型设备嵌入式系统(J2ME)的应用开发市场,其语言吸取了SmallTalk的一切皆对象的理念,摆脱了C++的历史累赘,简洁、 自由的风格赢得了很多开发者的喜爱。从JDK1.1开始,Java成为实用的语言,而不是被人观望的新品秀;再经过JDK1.2的大量增强(尤其是 Collection Framework),JDK1.3的虚拟机效率提升(HotSpot),JDK1.4的融合百家之长(Logging、 RegExp、NewIO等),现在已经是成熟稳重,颇显大家风范。
在企业级市场上,大部分的应用建立在数据库基础上,数据是企业的生命,传统开 发语言,包括面向过程的C、面向对象的C++、变种Pascal的Delphi(非常棒的语言,我用过四年),面向数据的PowerBuilder等等, 先后在数据库开发的舞台上展现风姿。Java当然不会放过这些,于是,出现了JDBC。在JDBC的帮助下,Java也迅速渗入数据库开发的市场,尤其是 面向企业服务器的应用开发。
今天要谈的JDO,与JDBC有非常密切的关系,尽管JDO并不是只面向JDBC的数据对象包装规范。下面先简单地介绍一下JDBC。
1.1 关系数据库之百家争鸣,ODBC
关 系数据库的历史一言难尽,我只能从我的接触经历和所见所闻,简单地叙述一下。最早的时候,计算机还只在一些大型的研究机关露面,并不是普罗大众可以涉及 的。苹果电脑将个人电脑引入民间,再随着IBM的PC标准开放,个人电脑逐步普及开来,加上微软的DOS操作系统,以及Borland的Turbo系列语 言开发环境,老百姓发现原来电脑可以做这么多事!后来,出现了DBASE,一个简单的关系数据库系统,和SQL语言。后来,Borland看到了数据库的 市场前景,推出了Paradox(也是当今Delphi和C++Builder中仍然使用的Paradox),一举占领了民用数据库的大部分江山,之后, Borland干脆收购了Dbase,后来又购买了InterBase,将数据库市场的领先优势一直保持到Windows3.0出现。这时候,微软在 Windows1.0和2.0被人痛骂之后顽强地推出3.0,以及更稳定的3.1和Win32API,造就了个人电脑桌面操作系统的霸主地位,在 Borland未警觉的情况下,购买了同样具有类Dbase数据库技术的Fox公司,并迅速将其易用化,形成了FoxBase,后来演变成FoxPro, 逐渐超过了Borland,成为个人电脑数据库的大户。微软再接再励,为简单易用而低负荷要求的数据库应用开发了Access,赢得了广大开发人员的心。 当然,同期的Oracle、Sybase、Informix等商用数据库凭专注于企业级数据库技术成为高端的几位领军人物。微软当然也想成为高端数据库供 应商之一,于是自行开发一套面向企业级应用的数据库,不过很快项目夭折,微软不甘心,购买了Sybase的底层TDS技术,包装成了 SQL Server,凭微软的高度易用性的特点,也占领了不少市场。
当市场上出现众多的数据库产品之后,Borland和微软都发现自己拥有的 数据库产品挺多,市场也不小,不同的产品给用户带来不同的配置任务,不利于所有产品的推广,于是,两者纷纷开始制定数据库访问的规范,微软推出了 ODBC,其面向开发人员的亲和性,逐步获得了认可,同时,Borland纠集了IBM和Novell也推出了IDAPI数据库接口规范,也就是今天 BDE的核心,不过后来Novell和IBM先后退出,只剩Borland独力支撑。不过Borland是一个技术实力雄厚的公司,其技术一向领先于微 软,BDE的性能比初期的ODBC不知道要好多少倍,后来微软偷师学艺,把连接池等技术加到ODBC中,在Delphi3.0及其BDE在市场上风光无限 的时候,逐步赶了上来并有超过。直到今天,BDE仍是Borland的产品线上的数据库访问标准,而微软如果不是将ODBC和多数数据库的客户端内嵌进 Windows的话,估计BDE仍是市场的赢家。不过,微软是玩弄市场的老手,通过对操作系统的垄断,其数据库产品和ODBC标准终究占据了多数开发市 场。
1.2 从optional pack到JDK的标准API
Java开始涉及数据库应用后,Sun就极力制 定Java的数据库规范,JDBC API就是类似ODBC一样,对数据库访问的底层协议进行最基本的包装,然后形成一套统一的数据访问接口,数据库连 接、SQL语句句柄、结果集,都带有ODBC的影子。以方便配置为目的,Sun极力推荐完全瘦客户端的TYPE 4型JDBC驱动,这是一个不需要安装数 据库客户端的驱动规范,是现在使用最多的。当然,为了保持与旧的数据库兼容,JDBC规范中包括了专用于连接ODBC的TYPE 1驱动和需要安装数据库 客户端的TYPE 2驱动,以及可以由厂商在数据库服务端专门提供面向JDBC的服务的TYPE 3驱动。
JDBC最早出现时,还不属于标准JDK的一部分,而是作为一个额外包提供下载。后来,随着Java编写的数据库应用的的增多,和JDBC规范本身的逐渐成熟,JDBC终于成为JDK1.1的一部分。
JDBC 目前最新的是3.0版本,还有正在讨论中的4.0版本。实际上,在开发中使用得最多的还是1.0中的API,2.0中主要增加了可双向滚动的结果集、更新 批处理等提高可用性和性能的API,3.0主要增加了连接池、可更新的结果集等特性。4.0将在可管理性、连接池规范化等方面再做改进。
2 面向对象与数据库
现在的程序员,没有不知道面向对象的。作为接近真实客观世界的开发概念,面向对象使程序代码更易读、设计更合理。在普遍存在的数据库应用领域,开发人员对面向对象的追求从未停止过。从八十年代开始,就有很多公司和研究机构在进行着面向对象与数据库结合的研究。
2.1 SmallTalk、C与C++、Delphi?DObject Pascal、Java
面 向对象的语言最早有好几种雏形,IBM的SmallTalk是其中最为流行的,在SmallTalk中,一切都是对象,一切都是类,它将面向对象的概念发 挥到了极致。面向对象的编程比起传统的面向过程的方式挺进了一大步,使人们认识到:原来软件可以这样写。不过,由于计算机基本结构与底层硬件体系和系统软 件的限制,SmallTalk还不能在理想的性能前提下推广到普通的应用上,这一点暂时限制了SmallTalk的发展,接着,C语言的面向对象版C++ 出现了,由于使用C语言的人很多,C++很快成为面向对象编程的主流语言。不过,为了保证与C的兼容,C++保留了很多面向过程的痕迹,比如恶心的指针、 全局变量等等。Pascal的改进版Object Pascal相对来说安全许多,后来Borland干脆将Object Pascal换了个名字,叫 Delphi,从此开创了一片面向对象编程的新世界, Delphi的严谨语法和快速编译吸引了众多的应用开发者,加上Borland的完美的VCL组件 体系,比起MFC来方便而容易,另外,Delphi完整的数据库组件,也将数据库开发变得简单而容易,Delphi再次成为成熟的面向对象开发语言。微软 当然不会放过这些,通过将MFC内置到操作系统中,微软的VC++也抢回一些市场。这也是为什么Delphi开发的应用程序编译后会比VC、VB开发的程 序大的原因。
1995年,Sun的一个开发小组本来为了小型嵌入式系统开发OAK语言,结果无心插柳柳成荫,发展出了Java语言,它是一个完全 摆脱了传统语言的各种负担的面向对象的语言,当然,也保留了一些非面向对象的核心(原始类型)以保证速度。现在Java也为最流行的面向对象语言之一。当 然,微软同样不会放过它,擅于模仿的微软立即弄出一个C#来与之竞争,并在C#中保留了一些变种的指针(指代)以吸引传统的C开发者。关于这些语言的各自 特点,这里就不一一赘述了。
2.2 数据库与数据对象化
数据库是企业级应用不可缺少的,因此,在面向对象流行的时候,数据库厂商也在进行着数据对象化的研究。这些研究在上个世纪八十年代就初现端倪。
数据库的对象化一般有两个方向:一个是在主流的关系数据库的基础上加入对象化特征,使之提供面向对象的服务,但访问语言还是基于SQL;另一个方向就是彻底抛弃关系数据库,用全新的面向对象的概念来设计数据库,这就是对象数据库ODBMS。
2.2.1 关系数据库对象化、SQL99与JDBC3.0随着许多关系数据库厂商开始提供对象化服务,各自的接口开始互不兼容,在经历一些麻烦之后,关系数据库厂商感觉到规范化的必要,因为当初关系数据库雄霸天下时SQL92标准起了很大作用,大家可以按照统一的编程方式来访问高性能的商用数据库。
关系数据库厂商集中起来,重新将对象化服务规范起来,形成了SQL99规范,将其中的对象结构等内容规范起来,开始一个崭新的面向对象的关系数据库(ORDBMS)的历程。
JDBC3.0就是在这种情况下出台的,它将对关系数据库中的对象服务的访问API规范起来,为Java平台提供了访问ORDBMS的标准方式。当然,JDBC3.0对传统的SQL操作也进行了很多功能增强。
Oracle 是一个传统的关系数据库厂商,在对象化的道路上,Oracle当然采取追加对象化特征的道路,以侵入数据对象化的市场,保持Oracle在数据库领域的领 导地位。如果说Oracle7.4使Oracle走向全盛的话,从Oracle8开始,Oracle就成为关系数据库加对象类型的先驱。在Oracle8 中,我们可以定义一些数据结构(Record),将普通的类型包装在其中成为数据元素,然后可以在客户端按Record结构进行访问,初步提供了面向对象 的数据库服务。
2.2.2 对象数据库
对象数据库就是采用全新的面向对象概念来设计数据库的全新数据库类型。在 这方面,主要以一些大学研究机构进行设计和开发,有些也形成了产品,不过由于市场方面的原因(主要是关系数据库的容易上手和市场绝对领导地位)和 ODBMS先天的一些弱点(比如查询引擎很难优化),使ODBMS没有象关系数据库那样流行起来。
不过对象数据库的对象化特点还是令人割舍不下, 目前还是有一些很好的产品在市场上,从商用的到免费的都用。目前在ODBMS领域占据领导地位的是Versant、FastObjects和 ObjectStore等几大厂商,并且,市场份额也在逐步扩展。免费的产品包括C++编写的Ozone、纯Java的db4o等等。还有一些研究机构开 发一些底层的面向对象数据库引擎,但只提供一些底层的API,不提供管理方面的功能,以及一些算法提供开放式接口,让厂商去选择和实现。比如美国威斯康新 大学计算机系数据库组的SHORE引擎,就是一个非常出色的面向对象数据库引擎,现在还在积极的更新中,一些其它研究机构和数据库厂商采用它完成了自己的 特别的对象数据库,比如专用于地理信息的数据库、专用于宇宙空间数据研究的数据库等等。
目前对象数据库最大的障碍是缺乏统一的规范,各个数据库厂商有各自的访问接口。对象数据库比起关系数据库来,不只是基本的几种数据类型那么简单,它还涉及继承处理、多态等一大堆面向对象特征的实现,规范化道路当然困难重重。这也是对象数据库无法普及的一个重要原因。
也 有一些机构提出了一些建议的规范,比如制定Corba标准的OMG小组的一个分组ODMG提出的ODMG规范,目前已经是3.0版本,其中的OQL对象查 询语言相当具有吸引力。还有一些中立的机构提出了其它的一些标准化的对象访问API,也可算是面向对象数据库的规范之一。象前面提到的 FastObjects和Ozone就是符合ODMG3.0规范的。
3 Java对象映射
话说回来,在一般的开 发人员眼中,数据库就是指关系数据库,因此,很多应用还是采用简单的JDBC来访问数据库。在开发的过程中,大家逐渐感觉到JDBC的局限性,比如调用复 杂、容易产生资源泄漏等等,与面向对象的Java语言有一段距离,因此,很多开发小组开始思考如何将应用中的数据进行对象化建模,然后再想办法与JDBC 结合起来,这就是Java数据库开发中的层出不穷的对象包装技术。
3.1 对象包装技术
3.1.1 传统包装与演变
传统包装顾名思义,就是最初出现的包装方式,很多公司都经历过这一步,产生了很多风格各异的包装方法。当然,笔者也有过还算丰富的尝试过程。
举例来说,如果我们有一个用户类:
public class User {
public int userId;
public String name;
public java.util.Date birthday;
}
我们可以将其当作一个简单的数据类,然后写一些工具方法来实现与JDBC的交互。这些方法,我们可以放到一个另外的工具类中,也可以放到User类中作为静态方法。这些方法包括简单的增、删、改、查(以Oracle为例):
public class User {
public int userId;
public String name;
public java.util.Date birthday;
public static User addUser(String name, Date birthday) throws SQLException {
Connection conn = …; //获取一个JDBC连接
PreparedStatement ps = conn.prepareStatement(“…”); // 获取一个序列值来作为用户标识
ResultSet rs = ps.executeQuery();
rs.next();
User user = new User();
user.userId = rs.getInt(1); //读取序列值为新用户标识
user.name = name;
user.birthday = birthday;
ps = conn.prepareStatement(“insert into ….”); //插入用户数据记录的SQL
ps.setInt(1,user.id);
ps.setString(2,user.name);
ps.setDate(3,user.birthday);
ps.executeUpdate();
rs.close();
ps.close();
conn.close();
return user;
}
public static void deleteUser(int userId) throws SQLException {
Connection conn = ….;
//…
}
public static User getById(int userId) throws SQLException {
//…
}
//…
}
以 上就是一个简单的数据包装的基本雏形,我们可以看到,这是一个非常简单的JDBC包装,一些代码可以模块化,以实现重用。另外,这段代码还有很大隐患,就 是中途如果出现异常的话,就会使系统出现JDBC资源漏洞,因为JDBC分配的资源(conn,ps,rs等)是不能被Java虚拟机的垃圾回收机制回收 的。因此,我们的addUser方法就需要改成下面的样子:
public static User addUser(String name, Date birthday) throws SQLException {
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
User user = new User();
try {
conn = …; //获取一个JDBC连接
ps = conn.prepareStatement(“…”); // 获取一个序列值来作为用户标识
rs = ps.executeQuery();
rs.next();
user.userId = rs.getInt(1); //读取序列值为新用户标识
user.name = name;
user.birthday = birthday;
ps = conn.prepareStatement(“insert into ….”); //插入用户数据记录的SQL
ps.setInt(1,user.id);
ps.setString(2,user.name);
ps.setDate(3,user.birthday);
ps.executeUpdate();
} finally {
//这里注意一定要按照创建的顺序关闭JDBC资源:
if(rs != null) try { rs.close(); } catch(SQLException ex) { ex.printStackTrace(); }
if(ps != null) try { ps.close(); } catch(SQLException ex) { ex.printStackTrace(); }
if(conn != null) try { conn.close(); } catch(SQLException ex) { ex.printStackTrace(); }
}
return user;
}
所有的数据库访问方法都必须进行这样的包装,当我们的数据类达到一定的数量后(比如十几个,几十个),这些方法占据了大量的代码,维护困难、出现BUG机会增多,并且不易排错,尤其是资源漏洞这种容易引起服务器稳定性问题的BUG。
为 了保持数据类的纯洁,我们可以将JDBC操作方法集中到一个公共工具类中去完成,这样,这个工具类会非常庞大,但每个数据类会变得很简单,这种方式,可以 称作是DataAccessObject模式,相当于EJB中的ValueObject,是脱离数据库细节的纯对象模型。
这些都是最基本的存储处理,在基本增删改查(这里的查指按关键字查找对象)的基础上,我们还需要进行复杂的匹配查询(SQL),这使得我们的存储处理代码进一步复杂化。简单地,我们可以写一个类似的方法:
public static Collection findBy(String sql) throws SQLException {
//… (这里获取JDBC连接)
Collection col = new Vector();
ps = conn.prepareStatement(sql);
rs = ps.executeQuery();
while(rs.next()) {
User user = new User();
user.userId = rs.getInt(1);
user.name = rs.getString(2);
user.birthday = rs.getDate(3);
col.add(user);
}
return col;
//… (同前,这里是清理JDBC资源的代码)
}
这就是一个查询接口的基本定义,查询采用的语言仍是SQL。
如果我们需要将参数从SQL串中独立出来以节省数据库的解析时间并规范化,我们还需要将查询条件作为参数传递到这个方法中去,方法的接口改为:
public static Collection findBy(String sql, Object[] params) throws SQLException {
//…
ps = conn.prepareStatement(sql);
for(int i = 0; i < params.length; i++) ps.setObject(i+1,params[i]);
//…
}
调用的时候sql参数中会包含一些“?”号,如:
select ID,NAME,BIRTHDAY from USER where … = ? and … > ? and …
当然,也有一些开发团队喜欢将所有可能的查询都写死成一个个的专用查询方法,在其中完成对应的SQL操作,这一点类似于EJBQL,只不过是将EJBQL中容器实现的功能通过手工编码来实现。这样做使得查询受到限制,但可以提供更保险的接口。
还 有一些开发人员看到每个类中写这样一些查询方法使得这个类的代码变得庞大,维护麻烦,便将所有的查询方法放到一个公共的工具类中去,只是在方法中再加入一 个参数:Class cls来表示需要查询哪个对象,使得每个数据类变得紧凑一些。当然,这样的结果是那个公共类变得异常庞大,谁维护谁倒霉,可以说是牺 牲一人,幸福团队。不过如果这个人心理素质不够好、压力承受能力不强的话,一些对数据类的改动可能会受到他的阻碍,这时候就是“一夫当关,万夫莫开”。
现在,我们已经实现了基本对象的包装,现在才能开始考虑更多的问题。首先,我们可能会从规范化的角度出发,给每一个属性加上读写访问器getter/setter,在前面的User类中,可能我们会将基本属性部分写为:
public class User {
private int userId;
private String name;
private Date birthday;
//以下是针对以上属性的getter/setter,一般可以用IDE工具生成
public int getUserId() { return userId; }
public void setUserId(int value) { userId = value; }
public String getName() { return name; }
public void setName(String value) { name = value; }
public Date getBirthday() { return birthday; }
public void setBirthday(Date value) { birthday = value};
//…
}
这样,一个比较规范的数据类包装就算完成了。
另 外,我们知道,面向对象概念中,一个属性可以是另一个对象,也就是说,对象之间是存在着引用关系的,这种关系还分为一对一、一对多、多对多等几种情况。从 一个既定对象出发,其某个属性可以是另一个对象,也可以是包含另一组对象的集合。那么,在我们的数据包装里面,当然最好也能方便地处理对象之间的关系。假 定现在我们又有一个数据类Group:
public class Group {
public int grouId;
public String groupName;
public Set users; //set of User
}
这里为了简单表明含义,暂不采用getter/setter。
而User对所属的Group有一个引用:
public Group belongTo;
在这里,User.belongTo和Group.users就是一个一对多的关系。
在 我们的数据类中,如何才能实现数据库的存取呢?就算是不考虑Group.users这个反向关系,光是User.belongTo就是一件头疼的事。如果 我们在取出一个User对象时同时将其Group对象也取出来,可以保证不会在访问某个用户的组时得到一个null。不过这样有几个缺点:
1. 数据类的存取处理(JDBC)变得复杂,需要执行很多SQL读取才行,有时候只需要访问User的基本属性时浪费时间和资源;尤其是对集合型属性的预读取,更加可怕
2. 如果按这个逻辑,双向的关系处理变得危险,很容易陷入死循环,如果要避免,必须在类代码中加入一些特别的机制,也是很麻烦的事
3. 如果对象之间的关系是更复杂的情况下,比如三个、四个对象之间互相关联,那就是一场噩梦,对代码的编写和维护都异常艰难
于是,很多开发人员自然而然地退后一步,在User类中只保留一个groupId,并不保存Group对象,这样,可以将User.belongTo属性变成int类型,而另外写一个getter方法:
public Group getBelongTo() {
return Group.findById(belongTo);
}
而在Group类中,干脆将users属性去掉,只保留一个方法:
public Set getUsers() {
return new HashSet(User.findBy(“select … from USER where BELONG_TO=?”,new Object[]{ new Integer(groupId) }));
}
也 许细心一点的读者已经看出来了,这里的几个方法都没有将SQLException捕捉,也没有在方法中声明,也就是说是有语法错误的,因为 SQLException不是一个RuntimeException。不错,确实是这样,不过我们这里为了简单明了起见,省掉这些处理,以更直接清楚地表 达意思。
这样,实际上,我们的对象关系包装已经名存实亡,在类的内部有很多用于访问所引用对象的复杂代码,这些已经违背了我们将对象关系保持的初衷。有些开发人员甚至不在类中保留访问关系对象的方法,而是在客户调用时再去访问另一对象类的读取方法,如:
…
User user = User.getById(…);
//对user对象进行一些访问,如显示其姓名等等
Group group = Group.findById(user.belongTo);
//对group对象进行一些访问,如显示组名等等
…
在这样的代码里,实际上我们已经从根本上退回了关系数据库的出发点,这与直接访问数据表有多大区别呢?只不过是在表上面套了一层貌似面向对象的皮而已。不幸的是,这种方式还存在于很多应用之中。
从前面提到的这些面向对象包装的细节问题,我们可以看到这种传统包装方式的一些主要的缺陷:
3.1.1.1 数据库命名与对象设计命名的一致性问题 很 多时候,我们兴致勃勃地设计好一个类图,并且经过评审之后,开始对它进行数据库包装,这时候,发现有些属性名在具体的数据库中与该数据库的关键字冲突,不 能用作表名或字段名,必须在数据表设计时采用另外的名称,或者很麻烦地加上引号来使用。于是,写数据库处理代码的人有意见了,他必须很清楚地记得一个属性 在类中是什么属性名,在表中又是什么字段名,在编写的类逐渐增多后,尤其是一个类经过历次变动之后,或者经过很长时间又需要改动,并去处理这些JDBC代 码时,代码维护人员简单要发疯了! 3.1.1.2 对象的查询仍局限于SQL这一点也是这种简单的包装方法最不能摆脱关系数据库的地方。上面也已经说过,一些命名冲突带来了很多维护工作量,代码中必须还保留数据表的命名体系,而不是对象类的命名体系。这将使调用人员仍需要清楚记得两套命名体系,无论时间经过多久,或者开发人员是否有流动。 此外,对于普遍需要用到的连表查询,也给应用开发带来困难,这些地方仍不能突破SQL的限制。 3.1.1.3 SQL资源占用多 在处理对象集合访问或者处理集合类型属性时,往往我们只能在同一个Connection中处理一切事务,这就要求一次性地将集合中的对象全部读入,如果集合很大的话,容易造成数据库拥塞,使得性能大打折扣,适得其反。这方面的优化也是很多开发人员一直在努力改进的。 3.1.1.4 对象关系处理复杂 前面提过,对象之间的关系处理上,普通的包装技术是一种表面上的处理,在访问时调用者仍需要用大量的代码进行处理,并且,这还只是读取,在写入关系属性时会有更多的细节问题需要处理。 3.1.1.5 面向对象特色只能应用一小部分 面向对象的包装到前面所说的为止,都还只是很基本的处理,而面向对象的精华:继承和多态,在这里得不到任何帮助。我们放弃了很多合理的设计来迁就数据库的包装。 以上就是基本数据包装的主要缺陷,还有更多的小问题也需要额外的处理。 3.2 面向对象的数据库查询在对数据库进行面向对象研究的过程中,软件世界的开发人员和设计人员们发现:对数据库能够进行对象化的查询,才是对数据库进行彻底的面向对象化。这体现在我们使用一种全新的数据库查询语言,能够很简洁易懂地对数据库中的对象进行查询。一个典型的例子如下: 由此可见,对象式的查询语言,比起实现同样功能的SQL语言来说,简单了很多,意义也更明确,更符合使用者的思维习惯。在类图比较复杂、查询涉及的类又比较多的时候,这种新型的查询语言体现出绝对的优势。 4 JDO历程与主要产品说起JDO,其来由还有一段特 殊的背景。Java语言在JDK1.1达到比较实用的目的后,企业级数据库应用也正是软件开发市场中的重要组成部分,Sun看到这一点后,也希望通过 Java这个强大的武器在数据库开发市场攻占市场份额。JDK1.2推出后,Sun同时推出了面向企业应用的EJB,对基于java的中间件服务器框架进 行了规范化定义,这就是J2EE。不过在JDK1.2时,Java的速度还是不能与传统的C/C++和Delphi这样一些应用开发语言相比。为了防止业 界对Java的激情因此而消退,Sun宣布将在JDK中加入强大的虚拟机技术HotSpot,其中包含更先进的垃圾收集算法和更优化的Java字节代码再 编译技术(相当于JIT,Java即时编译技术)。HotSpot引起了Java关注者的极大兴趣,但Sun的HotSpot一拖再拖,最后包含在 JDK1.3中出来时,性能也没有象预期的那样好,比起C++编译生成的代码来还是有一段距离。 4.1 规范提出、JSRJDO最早是由Sun召集众多的O/R Mapping开发团队集中起来共同提出的,首先是通过会议确定了JDO需要包括的内容,然后正式提出一个Java规范请求(JSR-12),正式开始了JDO规范的制定。下面是主要的进展里程碑。 4.2 Oracle与JDO作为JDO专家组的重要成员,同时作为最大的关系数据库厂商的Oracle地位显然非同一般。在JDO规范中,Oracle也可说是立下汗马功劳,很多API的形成,Oracle都提供了很重要的参考意见,最终的投票Oracle也是毫不犹豫。 4.3 主要产品以及各自特点在JDO 规范制定的同时,出现了几个主要的JDO产品,有美国的基于对象数据库的FastObjects j1、法国的支持Versant对象数据库、文件数据 库、主流RDBMS的LiDO、南非的JDOGenie、德国的JRelay等等,这些都是很不错的JDO产品。下面列举一下我对主要的几个产品的印象: 5 目前状况与未来展望从2002 年4月JDO1.0规范正式公布以来,各个产品层出不穷,从商业到免费的层次,都有不错的产品推出。象Kodo、Lido、JDOGenie等产品都已经 比较成熟,可以考虑投入开发使用。在2002年8月,JDO又推出1.0.1修正版,修正了1.0版规范中的一些文字错误,以及轻微地改进了部分异常定 义,不过改动都不大。从现在的情形来看,除了Kodo有一些大学的项目用到外,好象还没看到多少使用JDO作开发的应用。 在这里,笔者可以大胆地预测,在未来的一两年内,JDO将在Java世界大放光彩! 5.1 一点花絮在2003年6月举行的JavaOne大会上,JDO备受瞩目,很多开发者或开发组织对其产生了极大的兴趣,在各大网站媒体上也频频曝光,大多对其评价不错,当然,也有一些负面的评价。 本文的版权属于笔者本人,但欢迎转载,前提是注明出处和原作者。另外,欢迎在我的专栏中查看我的另几篇文章,并提出宝贵意见! |
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/374079/viewspace-130784/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/374079/viewspace-130784/
[转载]JDO之前世今生相关推荐
- Java数据对象(JDO)的前世今生
1 Java与数据库应用,JDBC Java发明以来,在短短的几年之间,迅速占领了从桌面应用(J2SE)到 服务器 (J2EE),再到小型设备 嵌入式 系统(J2ME)的应用开发市场,其语言吸取了Sm ...
- [转载]如何用JDO开发数据库应用(3)
如何用JDO开发数据库应用(3) 4.3. 编辑metadata: system.jdo 这个过程,我们完全可以通过JDOGenie带的图形工具来完成. 我 们将上面两个类编译以后,打开JDOGeni ...
- [转载]本土ERP软件的前世今生
本土ERP软件的前世今生 --15年的用友与10年的金蝶背后,是中国本土财务软件厂商整体缺钙的缩影 文/<知识经济e企业>记者辛云勇 表面上,用友金蝶们又回到了当年的起点.不过,这种戏剧性 ...
- 【转载】我眼中的信贷管理系统的前世今生
原帖地址:http://www.itpub.net/thread-1292233-1-1.html -----------------------分析的很好,看完转载如下--------------- ...
- async 和 await的前世今生 (转载)
async 和 await 出现在C# 5.0之后,给并行编程带来了不少的方便,特别是当在MVC中的Action也变成async之后,有点开始什么都是async的味道了.但是这也给我们编程埋下了一些隐 ...
- 【转载】async await 的前世今生(Updated)
async 和 await 出现在C# 5.0之后,给并行编程带来了不少的方便,特别是当在MVC中的Action也变成async之后,有点开始什么都是async的味道了.但是这也给我们编程埋下了一些隐 ...
- (转载)JDO快速入门(原理详解)
JDO快速入门 Java数据对象(Java Data Objects,JDO)是一个应用程序接口(API),它是Java程序员能够间接地访问数据库,也就是说,不需使用直接的结构化查询语言(SQL)语句 ...
- 【调侃】IOC前世今生(转载)
本文转自http://www.cnblogs.com/showjan/p/3950989.html#!comments 前些天,参与了公司内部小组的一次技术交流,主要是针对<IOC与AOP> ...
- 瓦片地图的前世今生(转载)
从古巴比伦黏土地图到今天的电子地图,从哥伦布航海图到现代化的卫星导航,地图的历史凝聚着人类的好奇和智慧,也掺杂着血腥和欲望.地图的历史足够厚重,因为地图关联着政治.军事.经济的沉浮:地图的历史也足够精 ...
最新文章
- springBean生命周期----来自spring实战总结
- Android 学习笔记
- 关于移动端上下滑动卡顿不流畅现象的解决方案
- php调用c windows,php:在WINDOWS中设置计划任务执行PHP文件_PHP教程
- 怎么可以用计算机弄出表白数字,怎么用数字表白 表白爱情数字大全
- Refused to display http localhost8080 xxx‘in a frame because it set ‘X-Frame-Options‘ to ‘DENY‘
- 进度条tqdm基本用法
- [BZOJ 4563]放棋子
- 写代码前的准备,你做好了吗?
- 计算机科学与应用考研题,2015年中科院计算机科学综合考研真题
- 我买了个阿里云服务器并在上面部署了一个项目
- 广东查出2190名裸官
- SAP 后台配置之FM基金管理篇
- Sensor系列五 App实现获取gsensor数据
- python循环3次停止_【Python】quot;为所欲为quot;怎么成语接龙?
- flask爱家租房项目开发(一)
- [渝粤教育] 广东-国家-开放大学 21秋期末考试马克思主义基本原理概论(A)10882k1 (3)
- Air780E模块AT固件和AT手册
- Django使用MySQL数据库
- 【MATLAB】手把手教你安装MATLAB R2021b(内含安装包)
热门文章
- 日文假名输入与键盘对应
- 论文笔记:Domain Randomization for Transferring Deep Neural Networks from Simulation to the Real World
- Linux 重置网卡流量统计
- 2017-2018-1 20155323 《信息安全系统设计基础》第9周学习总结
- Dcat Admin 批量操作/批量审批功能(弹窗)实现
- 学习工作必备的十二款常用在线工具,看完你不收藏算我输【强烈推荐】
- 妙健康:数字化精准健康管理平台,提供个性化健康解决方案
- 上任苹果 CEO 十年,这是库克给出的成绩单
- Wish卖家运营细节有什么?
- 高效能管理之要事第一 时间管理表格4