`

面向 Java 开发人员的 db4o 指南: 第 1 部分:简介和概览

    博客分类:
  • Java
阅读更多
      信息存储和检索作为同义语伴随 RDBMS 已经 10 来年了,但现在情况有所改变。Java 开发人员尤其厌倦于所谓的对象关系型阻抗失配,也对试图解决这个问题失去了耐心。再加上可行的替代方案的出现,就导致了人们对对象持久性和检索的兴趣的复 苏。本系列是对开放源码数据库 db4o 的详尽介绍,db4o 可以充分利用当前的面向对象的语言、系统和理念。要下载 db4o,可以参考 db4o 主页;为了实践本系列的示例,需要下载 db4o。Web Site : http://developer.db4o.com/
      早就听说数据库间的大战以关系型数据库的胜利告终。然而,这之后,编程界真的就风平浪静、一片繁荣了吗?持肯定观点的人恐怕最近都没有试过使用关系数据库来支持 Java™ 对象吧。著名作家和讲师 Ted Neward 为我们带来了这个由多个部分组成的 系列 ,深入介绍了 db4o,它是当前关系型数据库的一种面向对象的可选方案。

 

      在我出道成为程 序员的时候,数据库之战似乎已完全平息。Oracle 和其他几个数据库供应商都非常支持和看好关系模型及其标准查询语言 SQL。实际上,坦率地讲,我从未将任何关系数据库的直接祖先,比如 IMS 或无处不在的平面文件,用于长期存储。客户机/服务器看起来似乎长久不衰。

之 后,忽然有一天,我发现了 C++。正像许多在这个特别的时刻发现了这个特别的语言的其他人一样,它改变了我的整个编程 “世界观”。我的编程模型从基于函数和数据的变成了基于对象的。一时间,再也听不到开发人员大谈构建优雅的数据结构和 “信息隐藏” 了,现在,我们更热衷于多态封装继承 —— 一整套新的热门字眼。

关于本系列
信息存储和检索作为同义语伴随 RDBMS 已经 10 来年了,但现在情况有所改变。Java 开发人员尤其厌倦于所谓的对象关系型阻抗失配,也对试图解决这个问题失去了耐心。再加上可行的替代方案的出现,就导致了人们对对象持久性和检索的兴趣的复苏。 本系列 是对开放源码数据库 db4o 的详尽介绍,db4o 可以充分利用当前的面向对象的语言、系统和理念。要下载 db4o,可以参考 db4o 主页 ;为了实践本系列的示例,需要下载 db4o。

与此同时,关系数据库已风光不再,一种新的数据库 —— 对象数据库 —— 成为了人们的新宠。若能再结合一种面向对象的语言,例如 C++ (或与之类似的编程新贵,Java 编程),OODBMS 真是可以堪称编程的理想王国。

但 是,事情的发展并非如此。OODBMS 在 90 年代晚期达到了顶峰,随后就一直在走下坡路。原来的辉煌早已退去,剩下的只有晦涩和局限。在第二轮的数据库之战结束之时,关系数据库又成了赢家。(虽然大 多数 RDBMS 供应商都或多或少地采用了对象,但这不影响大局。)

上述情况中存在的惟一问题是,开发人员对 OODBMS 的热衷一直没有衰退,db4o 的出现就很好地说明了这一点。

对象和关系

对象关系型阻抗失配 这个话题完全可以拿出来进行学术讨论,但简单说来,其本质是:对象系统与关系系统在如何处理实体之间的互动方面所采取的方式是截然不同的。表面上看,对象系统和关系系统彼此非常合适,但若深入研究,就会发现二者存在本质差异。

首先,对象具有身份的隐式性质(其表征是隐藏/隐式的 this 指针或引用,它实际上是内存的一个位置),而关系则具有身份的显式性质(其表征是组成关系属性的主键)。其次,关系数据库通过隐藏数据库范围内的数据查询 和其他操作的实现进行封装,而对象则在每个对象上实现新的行为(当然,模块所实现的继承都在类定义中进行指定)。另外,可能也是最有趣的是,关系模型是个 封闭的模型,其中任何操作的结果都将产生一个元组集,适合作为另一个操作的输入。这就使嵌套的 SELECT 以及很多其他功能成为可能。而对象模型则无此能力,尤其是向调用程序返回 “部分对象” 这一点。对象是要么全有要么全无的,其结果就是:与 RDBMS 不同,OODBMS 不能从表或一组表返回任一、全部或部分列。

简言之,对象(用像 Java 代码、C++ 和 C# 这类语言实现)和关系(由像 SQLServer、Oracle 和 DB/2 这样的现代 RDBMS 实现)操作的方式有极大的差异。对于减少这种差异,程序员责无旁贷。

 



 

映射的作用

过 去,开发人员曾试图减少对象和关系间的这种差距,尝试过的方式之一是手动映射,比如通过 JDBC 编写 SQL 语句并将结果收集进字段。对这种方式的一个合理的质疑是:是否还有更简化的方法来进行处理。开发人员大都用自动的对象关系映射实用工具或库(比如 Hibernate)来解决这个问题。

即使是通过 Hibernate(或 JPA、JDO、Castor JDO、Toplink 或任何可用的其他 ORM 工具),映射问题也无法彻底解决,它们只会转移到配置文件。而且,这种方式与要解决的问题颇有些风马牛不相及。比方说,如果您想要创建一个分层良好的继承 模型,将它映射到表或一组表无疑是失败之举。若用对常规形式的违背来换取查询的性能,就会将 DBA 与开发人员在某种程度上对立起来。

可问题是很难构建一个富域模型(参见 Martin Fowler 和 Eric Evans 各自所著的书),不管是您以后想要调整它来匹配现有的数据库模式,还是想要调整数据库执行其操作的功能来支持对象模型(甚或这两者)。

但如果能不调整,岂不是更好?

 





 

进入 db4o:OODBMS 的回归

db4o 库是最近才出现在 OODBMS 领域的,它使 “纯对象存储” 的概念在新一代对象开发人员中重获新生。(他们笑称,现在不是很流行怀旧么。)为了让您对如何使用 db4o 有一个概念,特给出如下代表单个人的一个基本类:

注意: 如果还尚未下载,请现在就 下载 db4o 。为了更好地进行讨论(或至少编译代码),db4o 是必需的,本系列的后续文章也会用到它。


清单 1. Person 类

                package com.tedneward.model;

public class Person
{
    public Person()
    { }
    public Person(String firstName, String lastName, int age)
    {
        this.firstName = firstName;
        this.lastName = lastName;
        this.age = age;
    }
    
    public String getFirstName() { return firstName; }
    public void setFirstName(String value) { firstName = value; }
    
    public String getLastName() { return lastName; }
    public void setLastName(String value) { lastName = value; }
    
    public int getAge() { return age; }
    public void setAge(int value) { age = value; }

    public String toString()
    {
        return 
            "[Person: " +
            "firstName = " + firstName + " " +
            "lastName = " + lastName + " " +
            "age = " + age + 
            "]";
    }
    
    public boolean equals(Object rhs)
    {
        if (rhs == this)
            return true;
        
        if (!(rhs instanceof Person))
            return false;
        
        Person other = (Person)rhs;
        return (this.firstName.equals(other.firstName) &&
                this.lastName.equals(other.lastName) &&
                this.age == other.age);
    }
    
    private String firstName;
    private String lastName;
    private int age;
}

 

在众多的类中,Person 类显得极为寻常;还很简单。但若深入探究,就不难看出这个类会呈现出非常类似于对象的有趣属性和功能,例如它可以有配偶类,也可以有子类,等等。(我在后续的专栏中会历数这些属性和功能;现在,我只侧重于进行概括介绍。)

在基于 Hibernate 的系统中,将这个 Person 类的一个实例放入数据库,需要如下几个步骤:

  1. 需要创建关系模式,向数据库描述类型。
  2. 需要创建映射文件,用这些文件将列和数据库的表映射到域模型的类和字段。
  3. 在代码中,需要通过 Hibernate 打开到数据库的连接(用 Hibernate 术语来说,就是会话 ),并与 Hibernate API 进行交互来存储对象和将对象取回。

上述操作在 db4o 中出奇地简单,如清单 2 所示:


清单 2. 在 db4o 内运行 INSERT

                import com.db4o.*;

import com.tedneward.model.*;

public class Hellodb4o
{
    public static void main(String[] args)
        throws Exception
    {
        ObjectContainer db = null;
        try
        {
            db = Db4o.openFile("persons.data");

            Person brian = new Person("Brian", "Goetz", 39);
            
            db.set(brian);
            db.commit();
        }
        finally
        {
            if (db != null)
                db.close();
        }
    }
}

 

这样就行了。无需生成模式文件,无需创建映射配置,需要做的只是运行客户机程序,当运行结束时,为存储在 persons.data 中的新 “数据库” 检查本地目录。

检索所存储的 Person 在某些方面非常类似于某些对象关系型映射库的操作方式,原因是对象检索最简单的形式就是按例查询(query-by-example) 。只需为 db4o 提供相同类型的一个原型对象,该对象的字段设置为想要按其查询的值,这样一来,就会返回匹配该条件的一组对象,如清单 3 所示:


清单 3. 在 db4o 内运行 INSERT(版本 1)

                import com.db4o.*;

import com.tedneward.model.*;

public class Hellodb4o
{
    public static void main(String[] args)
        throws Exception
    {
        ObjectContainer db = null;
        try
        {
            db = Db4o.openFile("persons.data");

            Person brian = new Person("Brian", "Goetz", 39);
            Person jason = new Person("Jason", "Hunter", 35);
            Person clinton = new Person("Brian", "Sletten", 38);
            Person david = new Person("David", "Geary", 55);
            Person glenn = new Person("Glenn", "Vanderberg", 40);
            Person neal = new Person("Neal", "Ford", 39);
            
            db.set(brian);
            db.set(jason);
            db.set(clinton);
            db.set(david);
            db.set(glenn);
            db.set(neal);

            db.commit();
            
            // Find all the Brians
            ObjectSet brians = db.get(new Person("Brian", null, 0));
            while (brians.hasNext())
                System.out.println(brians.next());
        }
        finally
        {
            if (db != null)
                db.close();
        }
    }
}

 

运行上述代码,会看到检索出两个对象。

 




 

但是...

在您将我定义为狂热的推崇者之前,请允许我先列举几条反对 db4o 的言论。

db4o 几乎无法对应于现有的 Oracle、SQLServer 或 DB2!
完 全正确。相比之下,db4o 更适合于 MySQL 或 HSQL,这使其对于大量项目来说已经足够。更为重要的是,开销一直是 db4o 开发人员特别关注的事情,这又让它特别适于小型的嵌入式环境。(我这里给出的示例只是一个简单的演示,和其他任何小型的演示一样,请务必清楚一点,即姑且 不论它相比其他工具具有多少潜力,db4o 都会比您在这里所看到的要强大许多。)

我不能用 JDBC 在 db4o 上进行查询!
确 实如此,尽管 db4o 团队曾想过创建 JDBC 驱动程序以让对象数据库能接受 SQL 语法,即一种所谓的 “关系对象映射”。(开发团队之所以没有这么做,据说是因为没有这个必要,而且性能会因此大受影响。)问题的关键是,您在实现中使用的是对象 (POJO),除此之外别无他物。若不存储关系,为何还要使用 SQL 呢?

但是我的其他程序如何获得数据呢?
这要看具体情况。如果您这里所谓的 “其他程序” 指的是其他 Java 代码,那么只需在这些程序内使用 Person 类的定义并将其传递进 ObjectContainer ,正如我这里所做的一样。在 OODBMS 内,类定义本身就充当模式,所以无需其他的工具来获取 Person 对象。但是如果您这里所谓的 “其他程序” 指的是其他语言的代码,那么问题就会复杂一些。

对于 db4o 不支持的语言,比如 C++ 或 Python,数据基本上是访问不到的,除非是您能从 Java 代码构建程序。db4o 适用于 C# 和其他的 .NET 语言,而其数据格式在二者之间是兼容的,这就使得 Java 对象对同样定义的 .NET 类也可用。如果您这里所谓的 “其他程序” 指的是使用 SQL 和标准调用级接口(比如 ODBC 或 JDBC)来与数据库进行交互的报告工具,那么 db4o(或与此相关的任何 OODBMS)可能未必是很好的选择。机警的读者会发现报告功能现在对 OODBMS 还不可用,但好消息是:已针对此问题发起很多产品和项目,而且 db4o 还支持 “复制(Replication)”,它允许 db4o 实例将数据从其自身的存储格式复制进 RDBMS。

但它是个文件!
在 这种特殊情况下,确实如此;但正如前面所讲,db4o 在何处和如何存储数据方面十分灵活,而且还提供了一个轻量级的客户机/服务器选项。如果您所期待的是功能完善的 RDBMS 所能提供的冗余性,那么 db4o 并不能如您所愿(但其他的 OODBMS 能提供这类特性)。

但当我再次运行示例时,我会得到副本!(实际上,我每次运行该示例都会得到副本。)
这里,实际上回到了我们所讨论的第一个有趣的问题:身份,正是这一点将对象数据库和关系数据库区分开来。正如我前面所言,对象系统中的身份是通过隐式的 “this” 引用赋予的,Java 对象使用这个引用在内存中标识其自身。在对象数据库中,它被称为 OID对象标识符 ),该 OID 在 OODBMS 中充当主键。

当创建新对象并将其 “放” 进数据库中时,新对象并不具有与其相关的 OID,因而会收到其自身惟一的 OID 值。它会复制,就如同 RDBMS 在执行每个 INSERT 操作时生成主键所做的那样(比如 顺序计数器或自动增量字段)。换言之,就主键而言,OODBMS 与 RDBMS 相当接近,但主键本身并非传统 RDBMS(或过去习惯使用 RDBMS 的程序员)认为的那种主键。

换言之,db4o 旨在解决某些方面的问题,而不是成为解决全部持久性问题的一站式通用解决方案。实际上,这让 db4o 首轮就战胜了 OODBMS:db4o 无意向那些生产 IT 人员宣称自己是多么好的一种理念,以至于完全可以放弃他们在关系数据库上的投资。

 



 

结束语

传 统的集中关系型数据库作为数据存储和操纵的首选工具的地位在短期内无法撼动。以这种数据库为基础发展起来的工具非常之多,历史也很久远,而且许多程序员也 都陷在 “我们总需要数据库” 的思维模式之中,这些无疑加固了其地位。实际上,db4o 在技术上的设计和定位并不是为了挑战 RDBMS 的这一地位。

但 “面向服务” 社区迫切要求我们构建松散耦合的多层世界,当您开始将 OODBMS 放到这种环境中去审视的时候,有趣的现象就出现了:如果要实现组件(服务、层或诸如此类的东西)间真正的松散耦合,那么结果常常是某种程度的耦合只存在于 服务的调用程序和该服务的公开 API(或 XML 类型,不管您如何看待它)之间。无需数据类型,无需公开对象模型,无需共享数据库 —— 本质上讲,持久性方法仅仅是一个实现细节。因此,在大量场景中可用的持久性方法的范围会显著扩大。

分享到:
评论

相关推荐

    面向 Java 开发人员的 db4o 指南: 第 3 部分:db4o 中的数据库重构

    **db4o(Database for Objects)**是一款开源的对象数据库,专为Java开发人员设计,它允许开发者直接在数据库中存储和检索Java对象,无需进行传统的SQL映射。本指南的第三部分将深入探讨如何在db4o中进行数据库重构...

    面向 Java 开发人员的 db4o 指南 结构化对象和集合

    面向Java开发人员的db4o指南主要关注如何利用db4o进行结构化对象和集合的管理,从而提高开发效率和数据存储的灵活性。 **对象数据库** 与传统的关系型数据库(RDBMS)不同,对象数据库直接支持面向对象编程模型。在...

    面向Java开发人员的db4o指南db4o中的数据库重构.doc

    面向Java开发人员的db4o指南db4o中的数据库重构

    db4o使用指南

    "db4o 使用指南" db4o 是一个开源的面向对象数据库,能够轻松地将 Java 对象持久化到数据库中。本文将详细介绍 db4o 的安装、启动、查询方式、对象持久化、数据库文件结构、主要包结构等知识点。 一、db4o 安装和...

    db4o 权威指南

    《db4o 权威指南》是一本深入探讨db4o这一开源面向对象数据库系统的专业书籍,对于Java开发者来说尤其有价值。db4o是Database for Objects的缩写,它允许开发者以自然、直观的方式存储和检索Java对象,无需编写SQL...

    java数据库(db4o)

    Java数据库db4o,全称为“Database for Objects”,是一款开源的对象数据库系统,专门设计用于Java和.NET平台。它提供了一种直接在对象模型上进行数据操作的方式,无需传统的ORM(对象关系映射)层,简化了开发过程...

    DB4O Java开发应用

    DB4O,全称为“Database for Objects”,是一个开源的对象数据库管理系统,专为Java和.NET平台设计。它允许开发者直接在数据库中存储、检索、更新和删除Java对象,无需中间的ORM(对象关系映射)层。这篇文档是DB4O ...

    db4o开发指南和各种实例

    **db4o 开发指南与实例详解** **一、db4o 简介** db4o(Database for Objects)是一款开源的对象关系数据库管理系统(Object-Relational Mapping, ORM),它允许开发者直接将Java对象存储到数据库中,无需编写SQL...

    db4o中文指南

    db4o是一个专为Java和.NET开发者设计的开源、轻量级的纯面向对象数据库引擎,提供了一种简单易用的方式来实现对象持久化。这款数据库引擎已被验证具备优秀的性能,根据描述中的基准测试,db4o在与传统持久化方案的...

    db4o for java

    **db4o (Database for Objects) 是一个开源的、基于Java和.NET的面向对象数据库系统。它允许开发者直接在数据库中存储和检索Java或.NET对象,而无需传统的SQL查询语言,极大地简化了数据管理和持久化的流程。** 在...

    db4o8.0以及db4o中文指南

    **db4o 8.0 详解及中文指南** db4o(Database for Objects)是一款开源的对象数据库系统,它允许开发者直接将Java或.NET对象存储到数据库中,无需进行ORM(对象关系映射)。db4o的目标是简化数据管理,提供更接近...

    db4o-5.0-tutorial-java帮助

    描述:这份资料是关于db4o数据库的使用教程,特别针对Java开发人员。db4o是一款开源的对象数据库,支持Java、.NET以及Mono平台。该教程旨在帮助用户快速上手db4o,并在开发过程中提供可靠的支持。 ### 一、db4o概述...

    Db4o的简单操作项目

    Db4o,全称为“Database for Objects”,是一个开源的对象数据库管理系统,主要应用于Java和.NET平台。这个项目专注于提供一种简单的方式来存储和检索Java对象,无需SQL或其他中间映射层。在“Db4o的简单操作项目”...

    db4o6.4-java

    1. **对象持久化**:db4o能够将Java对象直接持久化到磁盘,对象的实例关系和结构被完整地保存下来,这使得在程序运行过程中可以方便地进行对象的创建、修改和查询。 2. **透明访问**:通过db4o,开发者可以像操作...

    db4o-7.2-java

    **db4o-7.2-java** 是一个针对Java平台的开源对象数据库系统,它将传统的关系型数据库理念与面向对象编程相结合,为开发者提供了一种高效、灵活的数据存储解决方案。db4o允许开发者直接存取Java对象,而无需通过SQL...

    db4o-8.0-java

    **db4o(Database for Objects)** 是一个开源的对象数据库管理系统(Object-Relational Mapping,ORM),它允许开发者直接在Java或.NET平台上存储和检索Java对象或.NET对象,无需进行SQL查询或者映射过程。db4o的...

    DB4O_java

    总之,DB4O是Java开发小型桌面应用程序的一个理想选择,它的简单易用和强大的功能使其在对象数据库领域占有一席之地。通过理解和掌握DB4O,开发者可以更高效地构建数据驱动的应用程序,同时享受对象数据库带来的便利...

    开源面向对象数据库 db4o 之旅

    1.介绍了面向对象数据库 db4o 的基本特性,并且与传统关系型数据库以及 OR 映射技术做了比较分析,读者可以体验到 db4o 的全新的面向对象存储的理念,并且给出了性能测试数据。 2.介绍了面向对象数据库 db4o 的安装...

    DB4O面向对象数据库使用指南

    DB4O面向对象数据库使用指南

    db4o-8.0.276.16149-java.rar

    db4o(Database for Objects)是一款开源的对象关系数据库管理系统(Object-Relational Mapping,ORM),专为Java和.NET平台设计。它允许开发者直接存取Java或.NET对象到数据库,而无需传统的SQL查询语言,简化了...

Global site tag (gtag.js) - Google Analytics