传统包装与演变

原创 2005年06月01日 23:35:00

传统包装与演变

  传统包装顾名思义,就是最初出现的包装方式,很多公司都经历过这一步,产生了很多风格各异的包装方法。当然,笔者也有过还算丰富的尝试过程。

  举例来说,如果我们有一个用户类:

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.1.2 产品化包装中间件

   面向对象的包装产品化后,逐步推广开来,称作关系/对象映射:O/R Mapping。并且,在产品化的过程中,产品提供者在产品中逐渐提供了更多的功能。先是一些自动命名转换器得以应用,将客户代码中的类名、属性名在内部 处理的时候自动地转换到对应的数据库结构命名空间上,这样,应用开发的时候不再关心具体的数据库结构,不再需要记忆不同地命名体系,只需要一心一意地根据 类图来进行开发。在此之后,这些O/R Mapping产品的开发团队又向前迈了一大步:引入了词法分析器,提供面向对象的查询语言!很多对象关系的查询使应用开发变得非常方便,使O/R Mapping产品上了一个新的台阶。

  3.1.2.1 TopLink

  TopLink是一个非常早期的产品,最 初面向C++,后来也实现了Java的映射。TopLink性能优异,功能强大,并且提供了独特的查询过滤器机制,以及对关系的处理和查询都非常有效,于 是,TopLink逐渐从商用化O/R Mapping产品中胜出,成为市场上的最出色的映射产品。也正因为这一点,最大的关系数据库厂商Oracle将其收购,成为提供最强数据库和最强对象映 射中间件的厂商。

  3.1.2.2 Castor、Hibernate

  TopLink虽然强大,但太强大的东西免 不了得意忘形,TopLink开始将用户锁死到自己的产品上,查询方式是最突出的。它的查询体系含有很多别扭的概念(在我看来是如此),但为达到一般 O/R产品不能达到的功能,开发者只能接受这些。慢慢地,也产生积怨,再加上其高昂的价格,让很多新老用户望而却步。于是,免费的产品开始崛起。

  免费的O/R Mapping工具有很多种,这里只提其中最有影响力的两种:Castor和Hibernate。

   Castor是Exolab组织开发的面向Java的包装工具,它最大的特色就是实现了大部分的ODMG OQL规范,在查询上,可以象完全使用一个对象数据库一样类图进行查询(后面会有介绍)。它的原理是通过Java反射API去实现属性的设置和读取。不过 由于各种原因,Castor后来的版本更新越来越慢,最终停步在1.0之前,成为至今未出到1.0正式版的O/R Mapping产品。不管怎么样,它还是一个相当不错的产品。
Hibernate是一个现在很火热的O/R Mapping产品,目前已经出到2.0版,它功能一样强大,同样使用Java反射API进行对象的设置,但它的查询语言就是一套比较独特的体系,这一点 有点类似TopLink,但Hibernate更具有亲和力,对关系的查询更方便,只不过比起Castor来,在方便性和规范性上还是稍逊一筹。就目前状 况而言,Hibernate的用户量和技术支持要强一些。

3.2 面向对象的数据库查询

  在对数据库进行面向对象研究的过程中,软件世界的开发人员和设计人员们发现:对数据库能够进行对象化的查询,才是对数据库进行彻底的面向对象化。这体现在我们使用一种全新的数据库查询语言,能够很简洁易懂地对数据库中的对象进行查询。一个典型的例子如下:
假设我们已经有前面提到的两个数据类:User和Group,它们之间有一对多的关系:User.belongTo和Group.users。在数据库中已经存在很多这两个类的实例,以及相互之间的关系。我们可以使用下面的对象式查询语言来查询符合条件的User对象:

select * from User where User.belongTo.name='GROUP1'
  
  或者

select userId,name from User where User.belongTo.name='GROUP2'

  等等。从中我们可以看出,通过使用面向对象中的成员属性指定符".",可以让我们达到SQL中的连表的效果,实际上,第一个句查询的SQL等价版本是:

select a.* from USER a, GROUP b
where a.BELONG_TO = b.GROUP_ID
and b.NAME = 'GROUP1'

  由此可见,对象式的查询语言,比起实现同样功能的SQL语言来说,简单了很多,意义也更明确,更符合使用者的思维习惯。在类图比较复杂、查询涉及的类又比较多的时候,这种新型的查询语言体现出绝对的优势。

  3.2.1 ODMG,OQL,Java Binding

   在面向对象式查询语言的研究过程中,开发人员们逐渐实现了相似的查询语言,然后互想取长补短,最终在ODMG组织(www.odmg.org)的统一 下,形成了规范化的语言:ODMG OQL,这是一种完全面向对象的数据库查询语言,语法与前面提到的类似,不过考虑了更广泛的情况,语句更加简洁而严谨。

  OQL并不是针对某种语言的,它可以被应用到很多种开发语言中,它不象SQL那样只是纯字符串式的查询语句,因为面向对象查询中还必须提供相关类的信息,所以OQL需要在编程语言中实现一些特定的API。

  目前,ODMG的OQL已经被规范化地应用到SmallTalk、Java、C++这些面向对象的程序设计语言当中,在ODMG的规范中,这几个模块被称作SmallTalk Binding、Java Binding和C++ Binding。

   不过,由于历史原因,ODMG并没有象想象中地那样得到广泛应用,现有的十几个面向对象数据库中,采用ODMG OQL规范的少之又少,目前也只有FastObjeccts、Ozone这些产品采纳了这个规范,而象Versant这样的大厂商还没有采取OQL来查询 数据库,而是自己定义了自己的一套API,称作VQL(Versant Query Lanaguage)。

  在JDO之前的O/R Mapping产品中,也有一些产品使用OQL(有时候是其子集),比如Castor、Apache的Jakarta小组开发的OJB等等。

  3.2.2 第三方协议

  软件世界是一个多姿多彩的世界,总有那么一些好事之士不断地冒出新奇的想法。还有一些开发面向对象数据库的组织制定了自己的一套对象式数据库查询语言,自己的规范。

  不过这些规范相对来说,影响力小得多。比起ODMG来,可以说应用范围太小,更不用说与SQL这样广泛应用的标准进行比较了。

  3.2.3 EJBQL

   Sun为了使Java应用在企业级数据库应用中,不遗余力地推广J2EE,在2001年的时候,推出了EJB2.0规范,其中包含了富有特色的面向 CMP方式的EntityBean的查询语言:EJBQL,功能类似于ODMG OQL,只不过只能在EJB发布时静态地存在于应用描述符中,不能在程序中动态地使用。这是EJBQL最大的弱点,也许EJB3.0规范会将其动态化,但 到了那一天,世界多半已经不是现在的样子了。

  3.2.4 JDO

  JDO中有最近规定的一个对象式查询语言规范, 称作JDOQL,比起OQL来,JDOQL将查询语言中的很多元素与Java语言紧密地结合在一起,有的人觉得麻烦,有些人觉得规范,评论各不相同。从笔 者个人的角度来看,这样有利于没写过数据库应用、没用过SQL的新手很快地习惯JDOQL,但实际上,有多少人会在没写过SQL,没了解过关系数据库的情 况下去用JDO写数据库应用呢?毕竟市场说明了一切。个人认为,JDO中对数据库对象的查询多少显得有些累赘,如果能更简化一点,那将更吸引使用传统 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++编译生成的代码来还是有一段距离。

  这个时候,大家开始对Sun心存怀疑,而Sun深知这一点, 于是将公众的注意力赶紧转移到EJB上,从EJB1.0到EJB1.1,再到EJB2.0,业界又开始关注J2EE中间件技术上来。很快,开发人同发现用 EJB来编写数据库应用还是有很大的难度,虽然在分布式技术上EJB确实有很大的价值。在这个时候,Sun决定推出JDO技术作为轻量级的Java数据库 访问规范,而这一点也受到很多传统O/R Mapping市场的欢迎。为了与传统O/R Mapping有所区别,Sun一开始就高姿态地将JDO定位成不只是面向关系数据库的Java规范,而是针对所有的存储技术,包括面向对象数据库和其它 类型的存储体系(如文件),就象EJB EntityBean一样,虽然。就笔者的角度,这个做法使第一版的JDO抛弃了很多传统O/R Mapping提供的面向关系数据库的功能,可以算是一个失策。

  4.1 规范提出、JSR

  JDO最早是由Sun召集众多的O/R Mapping开发团队集中起来共同提出的,首先是通过会议确定了JDO需要包括的内容,然后正式提出一个Java规范请求(JSR-12),正式开始了JDO规范的制定。下面是主要的进展里程碑。

JSR #000012 approved in July 1999

  1999-8组建的专家小组:包括Sun、Apple、BEA、IBM、Oracle、SAP、WebGain等

2000-5 完成公开评论草案
2000-6 在JavaOne上引入
2001-3 最终草案0.93
2001-5 最终草案0.96公布
2001-6 在JavaOne上启动
2001-11 最终草案0.98
2002-4 1.0版正式公布
2002-8 1.0.1修正版
2003-8 2.0规范启动


  4.2 Oracle与JDO

  作为JDO专家组的重要成员,同时作为最大的关系数据库厂商的Oracle地位显然非同一般。在JDO规范中,Oracle也可说是立下汗马功劳,很多API的形成,Oracle都提供了很重要的参考意见,最终的投票Oracle也是毫不犹豫。

   可是,世间的事总是变化莫测的,就在JDO1.0快出台之时,Oracle收购了TopLink,这一点使Oracle的身份变得特殊而复杂。 TopLink是一个商业产品,是以商业利益为目标的,而Oracle也是追求利益最大化的典型商家,这一点与JDO的开放精神背道而驰。因此,我们看到 后期Oracle对JDO的不积极态度,甚至在前一阵的JavaOne大会上有人从Oracle的角度非正式地攻击JDO。

  4.3 主要产品以及各自特点

   在JDO规范制定的同时,出现了几个主要的JDO产品,有美国的基于对象数据库的FastObjects j1、法国的支持Versant对象数据库、文件数据库、主流RDBMS的LiDO、南非的JDOGenie、德国的JRelay等等,这些都是很不错的 JDO产品。下面列举一下我对主要的几个产品的印象:

  LiDO(法国LibeLis公司)

  我对JDO的认识主要 是通过LiDO这个产品,它在2002年3月的一份图文并茂的教程中简要解说了JDO的使用和优点。这个教程可以在这里下载:http: //www.objectweb.org/conference/JDO.pdf。LiDO的特色是大而全,支持文件型数据库、RDBMS、ODBMS, 甚至是XML数据库。不过配置较麻烦。最新版本是2.0RC。

  KodoJDO(美国SolarMetrics公司)

  Kodo是JDO的中流砥柱之一,在JDO1.0还未最后通过的时候,它就是一个比较成熟的产品了,其特点是注重性能和稳定性,目前最新版本是2.5.0,是客户最多的产品。

  JDOGenie(南非HemSphere公司)

   这是目前我最推荐的产品,最新版本是1.4.7,性能也不错,稳定性还有待验证,但它有一个最大的特点:集成性好,最易学,其公司的CTO David Tinker也是一个善解人意的年轻人,采纳了很多网友的意见对产品进行改进,主要是在配置上非常方便,有一个专门的图形界面工具,可以进行配置、数据库 生成、对象查询等等很实用的功能。

  JRelay(德国ObjectIndustries公司)

  这也是一个出现得比较早的产品,也有一个GUI工具用于配置,曾几何时,这个工具还是相对很方便的,但一年多过去了,好象没什么进展,最新版本是2.0,我试过一段时间,后来就没有再跟进了。

  FrontierSuite for JDO (美国ObjectFrontier)

  这个产品与JRelay、Kodo一起,可算是早期的JDO三个主要产品,它支持正向开发和反向开发(Reverse Engineer)。它的特色是反向工程(从表结构生成数据类)比较方便,与UML的结合也很强,不过真正运行起来的时候,配置复杂。

  TJDO(一群跨国界的有志之士)

  这是一个在Sun提供的参考产品(Reference Implementation)的基础上加入一些扩展功能而形成的一个免费产品,目前最新版本是2.0beta3,不过进展也缓慢,这个版本已经出现好几个月了没有进一步的更新。

  5 目前状况与未来展望

   从2002年4月JDO1.0规范正式公布以来,各个产品层出不穷,从商业到免费的层次,都有不错的产品推出。象Kodo、Lido、JDOGenie 等产品都已经比较成熟,可以考虑投入开发使用。在2002年8月,JDO又推出1.0.1修正版,修正了1.0版规范中的一些文字错误,以及轻微地改进了 部分异常定义,不过改动都不大。从现在的情形来看,除了Kodo有一些大学的项目用到外,好象还没看到多少使用JDO作开发的应用。

   JDO毕竟是一个新技术,从概念上到实际应用上对其掌握的用户还不多,而这些产品在配置、使用上的方便性易用性还有待大幅度改进,因此,真正用JDO来开 发项目的用户还廖廖无几,至少我还不知道有哪些项目使用了JDO。我自己也尝试使用JDO来开发项目,但由于一些JDO1.0版本中还不够完善的一些硬伤 (比如不支持关系数据库统计功能),使我对JDO仍处于观望阶段。

  在八月中旬进行的JDO2.0规划会议中,来自各国的各个JDO产 品厂商、JDO技术咨询公司、JDO研究机构的代表汇聚一堂,将各自收集到的用户对JDO2.0的需求总结起来,提出一个个的新的议题,并且确定了每个议 题的JDO规范撰写负责人,比如高级fetchGroup特性由目前实现得最好的JDOGenie的CTO David Tinker负责,关于managed-relationship特性由Kodo的产品总监负责,用户要求最多的JDO对象与 PersistenceManager的脱钩/重挂钩特性由Sun的Craig Russell亲自操刀,等等。

  最具有吸引力的 JDO2.0议题,笔者个人认为是专门为关系数据库设立的子规范JDO/R,这也是我一直以来最关心的,这将使目前JDBC的开发将可以被JDO完全取 代,并且保证开发过程保持面向对象的特色。还有一些将一个类映射到多个表之类的特性也在规范化的列表上,这将有利于DBA在不影响应用开发的前提下根据需 要更改数据表结构,实现更好的性能。类似的新特性还有很多,粗略地看,这些都规范化起来后,真不知道各个厂商还能做什么样的扩展特性,也许以后厂商之间拼 的只能是技术支持服务和产品性能了,当然,最后还有价格的竞争。

  说了这么多,我想大家关心的还是JDO2.0到底什么时候能出 来,我们什么时候可以用上它,什么时候有中文版产品,价格到底如何。这些问题目前笔者还无法一一回答,只能根据笔者所掌握的信息初步解释一下。据前几天的 JDO2.0启动大会上David Jordan的预期,JDO2.0正式版将在18个月后正式完成。那正式完成后厂商什么时候才能提供符合规范的产品呢?这个问题不用担心,因为规范在制定 的过程中会不断地公布公众预览版(Public Review),这样,厂商可以先实现其中的功能,等规范正式完成后,也不会有太大的变化,厂商也不会需要太多时间来跟进最终规范。所以,我估计一年之 后,我们就可以在JDO2.0上进行开发了。至于价格如何,1.0规范的产品初步印象是每个开发人员需要一个License,一个License大概 2000美元。如果JDO2.0产品的价格还保持这么贵的话(至少对中国用户来说),我们也还有很多免费(如JPOX,TJDO)或半免费(如 JCredo)产品可以选择。最后一个关于中文版的问题,有待于厂商对中国市场的考察,或者看看是否有国内的JDO产品了。不过,在JDO2.0规范制定 的同时,我们可以先集众人之力将其普及,使广大的使用Java语言进行数据库开发的开发人员都来认识JDO,了解JDO,甚至将其用到项目开发之中。

  也许,JDO的目标已经吸引了Java世界以外的人,微软发现了这一点,也立即计划在.NET体系中加入一个仿照JDO的中间件,具体是采用ObjectStore的产品,ObjectStore是一个同时做JDO和.NET-DO(姑且使用这个名称)的公司。

  在这里,笔者可以大胆地预测,在未来的一两年内,JDO将在Java世界大放光彩!

  5.1 一点花絮

  在2003年6月举行的JavaOne大会上,JDO备受瞩目,很多开发者或开发组织对其产生了极大的兴趣,在各大网站媒体上也频频曝光,大多对其评价不错,当然,也有一些负面的评价。

   不过,网站上的报道也不可尽信,比如服务器领域的权威网站TheServerSide.com上介绍JavaOne大会第二天关于JDO的一次会议的报 道就有误导之嫌,从报道的内容来看,好象会议用来答疑与交流的的最后五分钟全被一个好事者占据,这个人拼命鼓吹Oracle的TopLink解决方案和一 些易用性的改进,从而攻击JDO的市场前景。后来,我就这一信息与参加会议的JDO专家组的David Jordan交流时,他纠正了我的错误理解,实际情形是:那个好事者是一个积极的JDO拥护者,他花了超过五分钟时间向大家揭露Oracle的 TopLink改进实际上也是抄袭JDO的概念而进行的一些API改动!不过有一点是相同的,这个好事者占据了大家的提问时间,使这次会议在意犹未尽中结 束。

流媒体:浅谈传统媒体—>流媒体—>加P2P的流媒体的演变之路

之前一直以为流媒体是P2P,看了你的博客后对流媒体的原理有了一定的理解,而又查了查P2P,原来P2P是应用在流媒体应用中的一个技术,如果只用流媒体(不含P2P)的话流量压力还在服务器上,当流量大了还是...

【广告算法工程师入门 22】机制设计-传统机制设计演变与收入优化思考

机制设计的内容 机制设计分配函数和计费函数,分配函数一般就是排序函数了,那就需要考虑为哪些东西排序(广告的样式,图片,广告本身等),排序函数的具体形式(线性,折线,曲线等),排序函数中的可调参数等,一...

大型分布式网站演变过程.pptx

  • 2017年02月21日 13:29
  • 1005KB
  • 下载

【Gopher China 2015】gofmt 的文化演变

  • 2015年04月28日 17:25
  • 9.97MB
  • 下载

从基础设施的演变,看人工智能到底需要什么样的底层平台

来源:亿欧 概要:大数据、大容量存储、弹性计算和各类算法的发展,尤其是在深度学习领域的发展,带来了各类脑洞大开的创新应用。 机器学习和人工智能的时代已经到来。大数据、大容量存储、弹性计...

微软的Logo演变史 含全图

  • 2013年11月28日 19:58
  • 163KB
  • 下载

天猫“双11”狂欢节背后:阿里巴巴加速新技术演变

关注ITValue,查看企业级市场最新鲜、最具价值的报道!   2017年天猫“双11” 不仅是全民购物狂欢节,更是阿里巴巴的新技术狂欢秀。机器人“鲁班”、智能客服“店小秘”、天猫精灵...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:传统包装与演变
举报原因:
原因补充:

(最多只允许输入30个字)