面向对象数据库 db4o 之旅Word格式.docx
《面向对象数据库 db4o 之旅Word格式.docx》由会员分享,可在线阅读,更多相关《面向对象数据库 db4o 之旅Word格式.docx(40页珍藏版)》请在冰豆网上搜索。
privateintage;
publicStringgetName(){
returnname;
}
publicintgetAge(){
returnage;
}
考虑下面这个场景:
找到“年龄小于20岁的所有学生”?
使用ORL实现如清单2:
清单2ORL实现
Stringoql="
select*fromstudentinAllStudentswherestudentage<
20"
;
OQLQueryquery=newOQLQuery(oql);
Objectstudents=queryexecute();
使用JDOQL实现如清单3:
清单3JDOQL实现
Queryquery=persistenceManagernewQuery(Studentclass,"
age<
);
Collectionstudents=(Collection)queryexecute();
上面的方法都存在一些普遍问题:
∙现代集成开发环境不会检查内嵌字符串的语义和语法错误。
在上面所有查询语句中,age字段和数值20都被认为是数字类型,但是没有一个IDE或编译器能检查其实际正确性。
如果开发者混淆了查询代码-―比如,改变了age字段的名字或类型,将导致――上面所有的查询语句在运行时报错,而不会在编译时提示。
∙现代敏捷开发技术鼓励不断进行重构来维持清晰和与时俱进的类模型,以便准确重现不断演进的域模型。
如果查询代码难于维护,它会延迟决定重构的时间并不可避免的引入低质量代码。
∙所有列出的查询都直接用Student类的私有成员age,而不是使用它的公共接口studentgetAge(),因此他们都破坏了面向对象封装规则,违反接口和实现应该分离的面向对象法则。
∙所有的查询都非100%的原生。
既然存在如此多的问题,为什么不直接使用纯面向对象数据库呢?
有些开发者可能会说:
“它缺乏数学模型的支持,还不够成熟”。
的确,RDBMS发展了几十年才有今天的成就,已经非常完善了。
而技术的革新是无止境的,故步自封的永远都跟不上变化的脚步。
让我们来简单回顾一下对象数据库的发展史(资料来源于Wiki百科全书):
“面向对象数据库系统”这一术语第一次出现于1985年。
著名的研究项目包括:
Encore-Ob/Server(布朗大学),EXODUS(Wisconsin大学),IRIS(惠普),ODE(Bell实验室),ORION(MCC),Vodak(GMD-IPSI)和Zeitgeist(TexasInstruments)。
其中以ORION项目发表的论文数为最多。
MCC的WonKim将这些论文中最有价值的一部分汇编成书并由MIT出版社出版。
对象数据库管理系统为面向对象编程语言增加了持久的概念。
最早的商品化ODBMS出现在1986年,是Servio公司(现在的GemStone公司)和Ontos公司推出的。
后来(九十年代)ObjectDesign(ODI)、Versant、Objectivity、O2Technology、Poet、Ibex、UniSQL和ADBMATISSE等公司也加入了这个开拓行列。
而今天,一家来自加州硅谷的开源面向对象数据库公司db4objects为我们带来了db4o,一款性能卓越的纯面向对象数据库,也是我们这篇和后续文章将会介绍的主角。
db4o为我们带来的是这样一种面向对象的查询方式:
∙100%的原生查询语言应能用实现语言(Java或C#)完全表达,并完全遵循实现语言的语义。
∙100%的面向对象查询语言应可运行在自己的实现语言中,允许未经优化执行普通集合而不用自定义预处理。
∙100%的类型安全查询语言应能完全获取现代IDE的特性,比如语法检测、类型检测、重构,等等。
什么是db4o
“利用表格存储对象,就像是将汽车开回家,然后拆成零件放进车库里,早晨可以再把汽车装配起来。
但是人们不禁要问,这是不是泊车的最有效的方法呢。
”–EstherDyson
db4o是一个开源的纯面向对象数据库引擎,对于Java与NET开发者来说都是一个简单易用的对象持久化工具,使用简单。
同时,db4o已经被第三方验证为具有优秀性能的面向对象数据库,下面的基准测试图对db4o和一些传统的持久方案进行了比较。
db4o在这次比较中排名第二,仅仅落后于JDBC。
通过图1的基准测试结果,值得我们细细品味的是采用Hibernate/HSQLDB的方案和JDBC/HSQLDB的方案在性能方面有着显著差距,这也证实了业界对Hibernate的担忧。
而db4o的优异性能,让我们相信:
更OO并不一定会牺牲性能。
图1HSQLDB基准测试
同时,db4o的一个特点就是无需DBA的管理,占用资源很小,这很适合嵌入式应用以及Cache应用,所以自从db4o发布以来,迅速吸引了大批用户将db4o用于各种各样的嵌入式系统,包括流动软件、医疗设备和实时控制系统。
db4o由来自加州硅谷的开源数据库公司db4objects开发并负责商业运营和支持。
db4o是基于GPL协议。
db4objects于2004年在CEOChristofWittig的领导下组成,资金背景包括MarkLeslie、Veritas软件公司CEO、VinodKhosla(Sun公司创始人之一)、Sun公司CEO在内的硅谷高层投资人组成。
毫无疑问,今天db4objects公司是硅谷炙手可热的技术创新者之一。
db4o特性
db4o的目标是提供一个功能强大的,适合嵌入的数据库引擎,可以工作在设备,移动产品,桌面以及服务器等各种平台。
主要特性如下:
∙开源模式。
与其他ODBMS不同,db4o为开源软件,通过开源社区的力量驱动开发db4o产品。
∙原生数据库。
db4o是100%原生的面向对象数据库,直接使用编程语言来操作数据库。
程序员无需进行OR映射来存储对象,大大节省了程序员在存储数据的开发时间。
∙高性能。
图2为db4o官方公布的基准测试数据,db4o比采用Hibernate/MySQL方案在某些测试线路上速度高出44倍之多!
并且安装简单,仅仅需要400Kb左右的jar或dll库文件。
在接下来的系列文章中,我们将只关注在Java平台的应用,但是实际上db4o毫无疑问会很好地在NET平台工作。
图2db4o官方基准测试数据
∙易嵌入。
使用db4o仅需引入400多k的jar文件或是dll文件,内存消耗极小。
∙零管理。
使用db4o无需DBA,实现零管理。
∙支持多种平台。
db4o支持从Java11到Java50,此外还支持NET、CompactFramework、Mono等NET平台,也可以运行在CDC、PersonalProfile、Symbian、Savaje以及Zaurus这种支持反射的J2ME方言环境中,还可以运行在CLDC、MIDP、RIM/Blackberry、PalmOS这种不支持反射的J2ME环境中。
或许开发者会问,如果现有的应用环境已经有了关系型数据库怎么办?
没关系,db4o的dRS(db4oReplicationSystem)可实现db4o与关系型数据库的双向同步(复制),如图3。
dRS是基于Hibernate开发,目前的版本是10,并运行在Java12或更高版本平台上,基于dRS可实现db4o到Hibernate/RDBMS、db4o到db4o以及Hibernate/RDBMS到Hibernate/RDBMS的双向复制。
dRS模型如图3
图3dRS模型
结论
db4o因为其开源的理念,以及创新的实现,获得了JavaPro2006读者选择奖。
无论从成功案例还是db4o本身来看,这款纯面向对象数据库都值得我们关注,从官方论坛反馈情况看,有相当的用户准备把关系型数据库迁移到db4o。
而最新发布的55版本,更是把性能再次提升很多。
在接下来的文章中,我会继续和大家分享db4o给我们带来的这场面向对象数据库风暴。
第2部分:
db4o查询方式
这篇文章是db4o之旅系列文章的第二篇,介绍了面向对象数据库db4o的安装、启动以及三种查询语言,并对三种查询语言做了比较。
查看本系列更多内容
标记本文!
在db4o之旅系列文章的第一部分:
初识db4o中,作者介绍了db4o的历史和现状,应用领域,以及和ORM等的比较。
在这篇文章中,作者将会介绍db4o的安装、启动以及三种不同的查询方式:
QBE(QuerybyExample)、SODA(SimpleObjectDatabaseAccess)以及NQ(NativeQueries),并分别通过这三种不同的途径实现了两个关联对象的查询。
本文还示范了开发中最经常用到的几个典型功能的db4o实现。
下载和安装db4o
db4o所有最新的版本都可以直接在官方网站上下载,进入db4o的下载页面,我们可以看到最新的forJava稳定版本是55,包括JAR、源代码、入门文档、API等内容的完整的打包文件只有6MB,db4o还有一个对象数据库管理工具ObjectManager,目前版本是18(请在参考资源中下载)。
接着在Eclipse中新建Java项目,把db4o对象数据库引擎包db4o-55-java5jar导入进项目。
由于db4o支持多种版本的JDK,除了forJDK50的db4o-55-java5jar外,还有forJDK11、12-14的JAR包,以适应多种环境。
与Hibernate、iBATISSQLMaps相比,db4o更加自然,无需过多地引用第三方支持库。
开启数据库
db4o怎样进行对象持久化呢?
通过浏览目录可以发现,与传统的RDBMS一样,db4o也有自己的数据库文件,在db4o中数据库文件的后缀名是“*yap”。
让我们先来了解一下db4o对象数据库引擎的主要包结构:
∙comdb4o
comdb4o包含了使用db4o时最经常用到的功能。
两个最重要的接口是comdb4oDb4o和comdb4oObjectContainer。
comdb4oDb4o工厂是运行db4o的起点,这个类中的静态方法可以开启数据库文件、启动服务器或连接一个已经存在的服务器,还可以在开启数据库之前进行db4o环境配置。
comdb4oObjectContainer接口很重要,开发过程中99%的时间都会用到它,ObjectContainer可在单用户模式下作为数据库实例,也可作为db4o服务器的客户端。
每个ObjectContainer实例都有自己的事务。
所有的操作都有事务保证。
当打开ObjectContainer,就已经进入事务了,commit()或rollback()时,下一个事务立即启动。
每个ObjectContainer实例维护它自己所管理的已存储和已实例化对象,在需要ObjectContainer的时候,它会一直保持开启状态,一旦关闭,内存中数据库所引用的对象将被丢弃。
∙comdb4oext
你也许想知道为什么在ObjectContainer中只能看见很少的方法,原因如下:
db4o接口提供了两个途径,分别在comdb4o和comdb4oext包中。
这样做首先是为了让开发者能快速上手;
其次为了让其他产品能更容易的复制基本的db4o接口;
开发者从这一点上也能看出db4o是相当轻量级的。
每个comdb4oObjectContainer对象也是comdb4oextExtObjectContainer对象。
可以转换成ExtObjectContainer获得更多高级特性。
∙comdb4oconfig
comdb4oconfig包含了所有配置db4o所需的类。
∙comdb4oquery
comdb4oquery包包含了构造“原生查询,NQ(NativeQueries)”所需的Predicate类。
NQ是db4o最主要的查询接口。
db4o提供两种运行模式,分别是本地模式和服务器模式。
本地模式是指直接在程序里打开db4o数据库文件进行操作:
ObjectContainerdb=Db4oopenFile("
autoyap"
而服务器模式则是客户端通过IP地址、端口以及授权口令来访问服务器:
服务器端:
ObjectServerserver=Db4oopenServer("
1212);
servergrantAccess("
admin"
"
123456"
客户端:
ObjectContainerdb=Db4oopenClient("
192168010"
1212,"
两种方式都可以得到ObjectContainer实例,就目前JavaEE应用环境来看,服务器模式更有现实意义;
而本地模式更适合于嵌入式应用。
为了简化演示,本文在下面的例子都将采用本地模式。
在下面的例子里,我们都会用到下面两个对象:
People和AutoInfo对象。
People对象清单1:
清单1People对象
packagebo;
publicclassPeople{
privatejavalangInteger_id;
privatejavalangString_name;
privatejavalangString_address;
privatejavautilList<
AutoInfo>
_autoInfoList;
publicjavalangIntegergetId(){
return_id;
}
publicvoidsetId(javalangInteger_id){
this_id=_id;
publicjavalangStringgetName(){
return_name;
publicvoidsetName(javalangString_name){
this_name=_name;
publicjavalangStringgetAddress(){
return_address;
publicvoidsetAddress(javalangString_address){
this_address=_address;
publicjavautilList<
getAutoInfoList(){
returnthis_autoInfoList;
publicvoidaddAutoInfo(AutoInfo_autoInfoList){
if(null==this_autoInfoList)
this_autoInfoList=newjavautilArrayList<
();
this_autoInfoListadd(_autoInfoList);
}
AutoInfo对象清单2:
清单2AutoInfo对象
publicclassAutoInfo{
privatejavalangString_licensePlate;
privateboPeople_ownerNo;
publicjavalangIntegergetId(){
publicvoidsetId(javalangInteger_id){
publicjavalangStringgetLicensePlate(){
return_licensePlate;
publicvoidsetLicensePlate(javalangString_licensePlate){
this_licensePlate=_licensePlate;
publicboPeoplegetOwnerNo(){
returnthis_ownerNo;
publicvoidsetOwnerNo(boPeople_ownerNo){
this_ownerNo=_ownerNo;
利用set方法把新对象存入ObjectContainer,而对ObjectContainer中已有对象进行set操作则是更新该对象。
db4o保存数据库很简单,下面就是一个段完整的保存对象的代码:
AutoInfo对象清单3:
清单3
packagecom;
importboAutoInfo;
importboPeople;
importcomdb4oDb4o;
importcomdb4oObjectContainer;
publicclassDB4OTest{
publicstaticvoidmain(String[]args){
//打开数据库
ObjectContainerdb=Db4oopenFile("
try{
//构造People对象
Peoplepeo=newPeople();
peosetId
(1);
peosetAddress("
成都市"
peosetName("
张三"
//构造AutoInfo对象
AutoInfoai=newAutoInfo();
aisetId
(1);
aisetLicensePlate("
川A00000"
//设置People和AutoInfo的关系
aisetOwnerNo(peo);
peoaddAutoInfo(ai);
//保存对象
dbset(peo);
}finally{
//关闭连接
dbclose();
}
当我们运行上述代码,db4o会自动创建“autoyap”文件。
让我们来看看到底保存成功没有,打开ObjectManager工具,如图1所示。
图1对象数据库管理工具
“File”->
“OpenFile”->
选择刚才我们保存的“autoyap”文件(“autoyap”文件可在项目的根目录下找到),最新的ObjectManager18版本为我们提供了“ReadOnly”方式读取数据库文件,避免ObjectManager占用数据库文件所导致的程序异常。
打开之后,如图2所示,刚才存贮的People对象已经在数据库中了,并且还可以很直观的看到AutoIn