Java数据工具(JDO)的前世此生
副标题#e#
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驱动。
#p#分页标题#e#
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-Object 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开拓者。关于这些语言的各自特点,这里就纷歧一赘述了。
#p#副标题#e#
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 工具数据库
#p#分页标题#e#
工具数据库就是回收全新的面向工具观念来设计数据库的全新数据库范例。在这方面,主要以一些大学研究机构举办设计和开拓,有些也形成了产物,不外由于市场方面的原因(主要是干系数据库的容易上手和市场绝对率领职位)和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要领就需要改成下面的样子:
#p#分页标题#e#
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参数中会包括一些"?"号,如:
elect 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};
//…
}
这样,一个较量类型的数据类包装就算完成了。
#p#分页标题#e#
别的,我们知道,面向工具观念中,一个属性可以是另一个工具,也就是说,工具之间是存在着引用干系的,这种干系还分为一对一、一对多、多对多等几种环境。从一个既定工具出发,其某个属性可以是另一个工具,也可以是包括另一组工具的荟萃。那么,在我们的数据包装内里,虽然最好也能利便地处理惩罚工具之间的干系。假定此刻我们又有一个数据类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资源占用多
#p#分页标题#e#
在处理惩罚工具荟萃会见可能处理惩罚荟萃范例属性时,往往我们只能在同一个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 面向工具的数据库查询
在对数据库举办面向工具研究的进程中,软件世界的开拓人员和设计人员们发明:对数据库可以或许举办工具化的查询,才是对数据库举办彻底的面向工具化。这表此刻我们利用一种全新的数据库查询语言,可以或许很简捷易懂地对数据库中的工具举办查询。一个典范的例子如下:
#p#分页标题#e#
假设我们已经有前面提到的两个数据类: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++编译生成的代码来照旧有一段间隔。
#p#分页标题#e#
这个时候,各人开始对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 今朝状况与将来展望
#p#分页标题#e#
从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窜改!不外有一点是沟通的,这个功德者占据了各人的提问时间,使这次集会会议在意犹未尽中竣事。