`

面向 Java 开发人员的 db4o 指南: 第 6 部分:结构化对象和集合

    博客分类:
  • Java
阅读更多
面向对象应用程序大量使用继承,并且它们常常使用继承(或者 “是一个”)关系来分类和组织给定系统中的对象。在关系存储模式中使用继承比较困难,因为这种模式没有内在的继承概念,但它是 OODNBMS 中的一个核心功能。在本期的面向 Java™ 开发人员的 db4o 指南 中,您将会发现,作为一个核心功能,在 db4o 中创建查询时使用继承竟是如此的简单(而且功能强大)。

 

在本系列文章中,我使用 Person 类型来演示 db4o 的所有基本原理。您已经学会了如何创建完整的 Person 对象图,以细粒度方式(使用 db4o 本身的查询功能来限制返回的实际对象图)对其进行检索,以及更新和删除全部的对象图(设定一些限制条件)等等。实际上,在面向对象的所有特性中,我们只漏掉了其中一个,那就是继承。

关于本系列
信息存储和检索作为同义语伴随 RDBMS 已经有 10 余年了,但现在情况有所改变。Java 开发人员为所谓的对象关系型阻抗失配而沮丧,也不再有耐心去尝试解决这个问题。加上可行替代方案的出现,就导致了人们对对象持久性和检索的兴趣的复苏。 面向 Java 开发人员的 db4o 指南 对开放源码数据库 db4o 进行了介绍,db4o 可以充分利用当前的面向对象的语言、系统和理念。请访问 db4o 主页 并下载 db4o;您需要用它来完成本文中的例子。

我将演示的这个例子的最终目标是一个用于存储雇员数据的数据管理系统,我一直致力于开发我的 Person 类型。我需要这样一个系统:存储某个公司的员工及其配偶和子女的信息,但是此时他们仅仅是该系统的 Person (或者,可以说 Employees 是一个 Person ,但是 Persons 不是一个 Employee )。而且,我不希望 Employee 的行为属于 Person API 的一部分。从对象建模程序的角度公平地讲,按照 is-a 模拟类型的能力就是面向对象的本质。

我会用 Person 类型中的一个字段来模拟雇佣 的概念。这是一种关系方法,而且不太适合用于对象设计。幸运的是,与大多数 OODBMS 系统一样,db4o 系统对继承有一个完整的理解。在存储系统的核心使用继承可以轻松地 “重构” 现有系统,可以在设计系统时更多地使用继承,而不会使查询工具变得复杂。您将会看到,这也使查询特定类型的对象变得更加容易。

 

高度改进的 Person

清单 1 回顾了 Person 类型,该类型在本系列文章中一直作为示例使用:


清单 1. 改进之前的示例……

                
package com.tedneward.model;

import java.util.List;
import java.util.ArrayList;
import java.util.Iterator;

public class Person
{
    public Person()
    { }
    public Person(String firstName, String lastName, Gender gender, int age, Mood mood)
    {
        this.firstName = firstName;
        this.lastName = lastName;
        this.gender = gender;
        this.age = age;
        this.mood = mood;
    }
    
    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 Gender getGender() { return gender; }
    
    public int getAge() { return age; }
    public void setAge(int value) { age = value; }
    
    public Mood getMood() { return mood; }
    public void setMood(Mood value) { mood = value; }

    public Person getSpouse() { return spouse; }
    public void setSpouse(Person value) { 
        // A few business rules
        if (spouse != null)
            throw new IllegalArgumentException("Already married!");
        
        if (value.getSpouse() != null && value.getSpouse() != this)
            throw new IllegalArgumentException("Already married!");
            
        spouse = value; 
        
        // Highly sexist business rule
        if (gender == Gender.FEMALE)
            this.setLastName(value.getLastName());

        // Make marriage reflexive, if it's not already set that way
        if (value.getSpouse() != this)
            value.setSpouse(this);
    }

    public Address getHomeAddress() { return addresses[0]; }
    public void setHomeAddress(Address value) { addresses[0] = value; }

    public Address getWorkAddress() { return addresses[1]; }
    public void setWorkAddress(Address value) { addresses[1] = value; }

    public Address getVacationAddress() { return addresses[2]; }
    public void setVacationAddress(Address value) { addresses[2] = value; }

    public Iterator<Person> getChildren() { return children.iterator(); }
    public Person haveBaby(String name, Gender gender) {
        // Business rule
        if (this.gender.equals(Gender.MALE))
            throw new UnsupportedOperationException("Biological impossibility!");
        
        // Another highly objectionable business rule
        if (getSpouse() == null)
            throw new UnsupportedOperationException("Ethical impossibility!");

        // Welcome to the world, little one!
        Person child = new Person(name, this.lastName, gender, 0, Mood.CRANKY);
            // Well, wouldn't YOU be cranky if you'd just been pushed out of
            // a nice warm place?!?

        // These are your parents...            
        child.father = this.getSpouse();
        child.mother = this;
        
        // ... and you're their new baby.
        // (Everybody say "Awwww....")
        children.add(child);
        this.getSpouse().children.add(child);

        return child;
    }
    
    public Person getFather() { return this.father; }
    public Person getMother() { return this.mother; }
    
    public String toString()
    {
        return 
            "[Person: " +
            "firstName = " + firstName + " " +
            "lastName = " + lastName + " " +
            "gender = " + gender + " " +
            "age = " + age + " " + 
            "mood = " + mood + " " +
            (spouse != null ? "spouse = " + spouse.getFirstName() + " " : "") +
            "]";
    }
    
    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.gender.equals(other.gender) &&
                this.age == other.age);
    }
    
    private String firstName;
    private String lastName;
    private Gender gender;
    private int age;
    private Mood mood;
    private Person spouse;
    private Address[] addresses = new Address[3];
    private List<Person> children = new ArrayList<Person>();
    private Person mother;
    private Person father;
}

 

跟本系列的其他文章一样,我不会在每次更改时都展示完整的 Person 类,只逐步展示每次更改。在这个例子中,我实际上并没有更改 Person ,因为我将要扩展 Person ,而不是修改它。

 



 

区别雇员

需要做的第一件事是使我的雇员管理系统能够区别普通的 Person (例如雇员的配偶和/或子女)和 Employee 。从纯粹建模的立场来说,这个更改很简单。我只是向 Person 引入了一个新的派生类,这个类和目前涉及到的其他类都在同一个包中。毫无疑问,我将会调用这个类 Employee ,如清单 2 所示:


Listing 2. Employee 扩展 Person

                
package com.tedneward.model;

public class Employee extends Person
{
    public Employee()
    { }
    public Employee(String firstName, String lastName, String title,
                     Gender gender, int age, Mood mood)
    {
        super(firstName, lastName, gender, age, mood);
        
        this.title = title;
    }

    public String getTitle() { return title; }
    public void setTitle(String value) { title = value; }
    
    public String toString()
    {
        return "[Employee: " + getFirstName() + " " + getLastName() + " " +
            "(" + getTitle() + ")]";
    }
    
    private String title;
}
    

 

Employee 类的全部代码都在清单 2 中。从 OODBMS 的角度看, Employee 中的其他方法意义不大。在本讨论中需要记住的是 EmployeePerson 的一个子类(如果更加关心系统的建模过程,可以设想 Employee 中的其他方法,例如 promote()demote()getSalary()setSalary()workLikeADog() )。

 




 

测试新模型

对新模型的探察测试简单明了。我创建一个叫做 InheritanceTest 的 JUnit 类,目前为止,它是第一个较为复杂的对象集,充当 OODBMS 最初的工作内容。为了使输出(将会在清单 6 中见到)更加清晰,我在清单 3 中展示了带有 @Before 注释的 prepareDatabase() 调用:


清单 3. 欢迎加入本公司(您现在为我服务)

                
    @Before public void prepareDatabase()
    {
        db = Db4o.openFile("persons.data");

        // The Newards
        Employee ted = new Employee("Ted", "Neward", "President and CEO",
            Gender.MALE, 36, Mood.HAPPY);
        Person charlotte = new Person("Charlotte", "Neward",
            Gender.FEMALE, 35, Mood.HAPPY);
        ted.setSpouse(charlotte);
        Person michael = charlotte.haveBaby("Michael", Gender.MALE);
        michael.setAge(14);
        Person matthew = charlotte.haveBaby("Matthew", Gender.MALE);
        matthew.setAge(8);
        Address tedsHomeOffice = 
            new Address("12 Redmond Rd", "Redmond", "WA", "98053");
        ted.setHomeAddress(tedsHomeOffice);
        ted.setWorkAddress(tedsHomeOffice);
        ted.setVacationAddress(
            new Address("10 Wannahokalugi Way", "Oahu", "HA", "11223"));
        db.set(ted);
        
        // The Tates
        Employee bruce = new Employee("Bruce", "Tate", "Chief Technical Officer", 
            Gender.MALE, 29, Mood.HAPPY);
        Person maggie = new Person("Maggie", "Tate", 
            Gender.FEMALE, 29, Mood.HAPPY);
        bruce.setSpouse(maggie);
        Person kayla = maggie.haveBaby("Kayla", Gender.FEMALE);
        Person julia = maggie.haveBaby("Julia", Gender.FEMALE);
        bruce.setHomeAddress(
            new Address("5 Maple Drive", "Austin",
                "TX", "12345"));
        bruce.setWorkAddress(
            new Address("5701 Downtown St", "Austin",
                "TX", "12345"));
        // Ted and Bruce both use the same timeshare, apparently
        bruce.setVacationAddress(
            new Address("10 Wanahokalugi Way", "Oahu",
                "HA", "11223"));
        db.set(bruce);
        
        // The Fords
        Employee neal = new Employee("Neal", "Ford", "Meme Wrangler",
            Gender.MALE, 29, Mood.HAPPY);
        Person candi = new Person("Candi", "Ford",
            Gender.FEMALE, 29, Mood.HAPPY);
        neal.setSpouse(candi);
        neal.setHomeAddress(
            new Address("22 Gritsngravy Way", "Atlanta", "GA", "32145"));
        // Neal is the roving architect
        neal.setWorkAddress(null);
        db.set(neal);
        
        // The Slettens
        Employee brians = new Employee("Brian", "Sletten", "Bosatsu Master",
            Gender.MALE, 29, Mood.HAPPY);
        Person kristen = new Person("Kristen", "Sletten",
            Gender.FEMALE, 29, Mood.HAPPY);
        brians.setSpouse(kristen);
        brians.setHomeAddress(
            new Address("57 Classified Drive", "Fairfax", "VA", "55555"));
        brians.setWorkAddress(
            new Address("1 CIAWasNeverHere Street", "Fairfax", "VA", "55555"));
        db.set(brians);
        
        // The Galbraiths
        Employee ben = new Employee("Ben", "Galbraith", "Chief UI Director",
            Gender.MALE, 29, Mood.HAPPY);
        Person jessica = new Person("Jessica", "Galbraith",
            Gender.FEMALE, 29, Mood.HAPPY);
        ben.setSpouse(jessica);
        ben.setHomeAddress(
            new Address(
                "5500 North 2700 East Rd", "Salt Lake City", 
                "UT", "12121"));
        ben.setWorkAddress(
            new Address(
                "5600 North 2700 East Rd", "Salt Lake City",
                "UT", "12121"));
        ben.setVacationAddress(
            new Address(
                "2700 East 5500 North Rd", "Salt Lake City",
                "UT", "12121"));
            // Ben really needs to get out more
        db.set(ben);
        
        db.commit();
    }
    

 

跟本系列早先的探察测试示例一样,在每次测试完成后,我使用带 @After 注释的 deleteDatabase() 方法来删除数据库,以使各部分能够很好地分隔开。

让我们运行几个查询……

在实际运行这个方法之前,我将会检查在系统中使用 Employee 会有哪些效果(如果有的话)。希望从数据库获取所有 Employee 信息,这很正常 — 或许当公司破产时他们将会全部被解雇(是的,我知道,这样想很残酷,但我只是对 2001 年的 dot-bomb 事故还有点心有余悸)。最初的测试看起来很简单,正如清单 4 所示:


清单 4. Ted 说,“你被解雇了!”

                
@Test public void testSimpleInheritanceQueries()
{
    ObjectSet employees = db.get(Employee.class);
    while (employees.hasNext())
        System.out.println("Found " + employees.next());
}
    

 

当进行测试时,将会产生一个有趣的结果:数据库(我自己、Ben、Neal、Brian 和 Bruce)中只返回了 Employee 。OODBMS 识别出查询受到子类型 Employee 的显式约束,并且只选择了符合返回条件的对象。因为其他对象(配偶或者孩子)不属于 Employee 类型,他们不符合条件,所以没有被返回。

当运行一个返回所有 Person 的查询时,将会更加有趣,如下所示:


清单 5. 找到所有人!

                
@Test public void testSimpleNonEmployeeQuery()
{
    ObjectSet persons = db.get(Person.class);
    while (persons.hasNext())
        System.out.println("Found " + persons.next());
}
    

 

当运行这个查询时,每个单一对象 — 包括以前返回的所有 Employee — 都被返回了。从某种程度上说,这是有意义的。因为 Employee 是一个 Person ,由于建立在 Java 代码中的实现继承关系,因此满足返回查询的必须条件。

db4o 中的继承(以及多态)其实就是这么简单。没有用于查询语言的复杂的 IS 扩展,就不会引入不同于 Java 类型系统中现有概念的 “类型” 概念。我所指的只是期望作为查询的一部分的类型,而且这些是构成查询的主要成分。这跟在 SQL 查询中加入表格很相似,方法就是选择其数据应为查询结果一部分的表格。额外的好处是,“父类型” 也是作为查询的一部分隐式地 “加入” 的。清单 6 显示了 清单 3InheritanceTest 的输出:


清单 6. 多态发挥作用

                
.Found [Employee: Ted Neward (President and CEO)]
Found [Person: firstName = Charlotte lastName = Neward gender = FEMALE age = 35
mood = HAPPY spouse = Ted ]
Found [Person: firstName = Michael lastName = Neward gender = MALE age = 14 mood
 = CRANKY ]
Found [Person: firstName = Matthew lastName = Neward gender = MALE age = 8 mood
= CRANKY ]
Found [Employee: Bruce Tate (Chief Technical Officer)]
Found [Person: firstName = Maggie lastName = Tate gender = FEMALE age = 29 mood
= HAPPY spouse = Bruce ]
Found [Person: firstName = Kayla lastName = Tate gender = FEMALE age = 0 mood =
CRANKY ]
Found [Person: firstName = Julia lastName = Tate gender = FEMALE age = 0 mood =
CRANKY ]
Found [Employee: Neal Ford (Meme Wrangler)]
Found [Person: firstName = Candi lastName = Ford gender = FEMALE age = 29 mood =
 HAPPY spouse = Neal ]
Found [Employee: Brian Sletten (Bosatsu Master)]
Found [Person: firstName = Kristen lastName = Sletten gender = FEMALE age = 29 m
ood = HAPPY spouse = Brian ]
Found [Employee: Ben Galbraith (Chief UI Director)]
Found [Person: firstName = Jessica lastName = Galbraith gender = FEMALE age = 29
 mood = HAPPY spouse = Ben ]

 

您可能会感到奇怪,不管如何查询,返回的对象仍然是适当的子类型对象。例如,跟预期的一样,在上面的查询中当 toString() 被每个返回的 Person 对象调用时,Person.toString() 也正被每个 Person 调用。然而,因为 Employee 有一个重写的 toString() 方法,因此关于动态绑定的常用规则就不适用了。存储在 Employee 中的 Person 的各部分不会被 “切掉”,而当定期 SQL 查询未能成功地将派生子类表加入到 table-per-class 模型中时,这种被 “切掉” 的现象就会发生。

 





 

原生继承

当然,当继承条件扩展到原生查询中时,其功能就跟我所做过的简单对象查询一样强大。进行调用时,查询语法将会更加复杂,但是基本上遵循我以前所使用的语法,如清单 7 所示:


清单 7. 你是单身吗?

                
@Test public void testNativeQuery()
{
    List<Person> spouses =
        db.query(new Predicate<Person>() {
            public boolean match(Person candidate) {
                return (candidate.getSpouse() instanceof Employee);
            }
        });
    for (Person spouse : spouses)
        System.out.println(spouse);
}
    

 

下面的查询与我以前做过的查询在思想上类似,考虑系统中所有的 Person ,但是设置一个约束条件,只查找配偶也是一个 EmployeePerson — 调用 getSpouse() ,将返回值传递给 Java instanceof 运算符,这样就完成了查询(记住 match() 调用只返回 true 或者 false,表示候选对象是否应该返回)。

请注意如何通过更改在 query() 调用中传递的 Predicate 来更改隐式选择的类型条件,如清单 8 所示:


清单 8. 哇!办公室恋情!

                
@Test public void testEmployeeNativeQuery()
{
    List<Employee> spouses =
        db.query(new Predicate<Person>() {
            public boolean match(Person candidate) {
                return (candidate.getSpouse() instanceof Employee);
            }
        });
    for (Person spouse : spouses)
        System.out.println(spouse);
}
    

 

当执行此查询时,不会产生什么结果,因为现在此查询只查找配偶也在公司工作的 Employee 。目前,数据库中的雇员都不满足这个条件。如果公司雇佣 Charlotte,那么会返回两个 Employee :Ted 和 Charlotte(但是人家说办公司恋情永远不会发生)。

在很大程度上,就是这样。继承不会对更新、删除和激活深度产生任何影响,只会影响到对象的查询方面。但是回想起 Java 平台提供的两种形式的继承:实现继承和接口继承。前者通过各种 extends 子句来实现,而后者通过 implements 来实现。如果 db4o 支持 extends ,那么它也一定支持 implements ,您将会看到,这有利于实现强大的查询功能。

 





 

都是关于接口的

就像任何 Java (或 C#)编程人员使用了一段时间这种语言后认识到的,接口对于建模非常有用。尽管不会经常看到,接口具有强大的 “隔离” 交叉在传统实现继承行中的对象的能力;通过使用接口,我可以声明某些类型为 Comparable 或者 Serializable ,或者在本例中,Employable (是的,从设计的角度说这是大材小用了,但是用于教学还是很不错的)。


清单 9. 嘿,不再是 2001 年了!来为我工作吧!

                
package com.tedneward.model;

public interface Employable
{
    public boolean willYouWorkForUs();
}

 

角色和对象

一些对象模型将不适合我用接口和继承来模拟 Person 扮演的角色。例如,假设一个 Employee 的配偶决定也来此公司工作,有必要将他们从系统的 Person 中删除,然后重新插入到 Employee 中吗? 随着时间的流逝,角色也可能并且经常变化。我们不要期望更改对象的基类和接口类型,以适应角色的转变。

这是一个很普通的争议,如果能够从根本上解决的话,不属于本文讨论的范围。目前我们只能说,我对继承和接口的使用纯粹是出于演示和教学的目的。要想进一步学习,请参考 参考资料 中的 “Role object” 一节。

要看接口是如何工作的,我需要 Employable 接口的一个实体类继承,并且 — 或许您已经猜测到 — 这意味着创建一个 EmployablePerson 子类型来扩展 Person 和实现 Employable 。我不会再次演示这些代码(没有必要演示,除了将 ** EMPLOYABLE ** 添加到 PersontoString() 末尾以外, PersonEmployablePerson.toString() 方法中)。我也会修改 prepareDatabase() 调用以返回 “Charlotte 是一个 EmployablePerson ,而不只是一个 Person ” 的事实。

现在,我会编写一个遍历数据库的查询,查找愿意为本公司工作的雇员的配偶或亲人,如清单 10 所示。


清单 10. 有工作了,来看看吧……

                
@Test public void testEmployableQuery()
{
    List<Employable> potentialEmployees =
        db.query(new Predicate<Employable>() {
            public boolean match(Employable candidate) {
                return (candidate.willYouWorkForUs());
            }
        });
    for (Employable e : potentialEmployees)
        System.out.println("Eureka! " + e + " has said they'll work for us!");
}    
    

 

毫无疑问,Charlotte 被返回了,说明她可能为本公司工作。更好的是,这意味着我引入的任何接口都变成了一种限制查询的新方式,不需要人工添加包含此信息的字段;只有 Charlotte 符合查询条件,因为她实现了这个接口,而其他配偶都没有实现(至少到目前为止)。

结束语

如 果说对象和继承就像巧克力和花生酱的话,那对象和多态就好比手和手套。这两个元素就像经理和他/她的高薪一样般配。检索数据时,任何存储对象的系统都不得 不将继承的概念引入它的存储媒介和过滤器中。幸运的是,面向对象的 DBMS 使得这很容易实现,而且不必引入新的 query-predicate 术语。从长远看来,引入继承会使 OODBMS 容易使用 得多

分享到:
评论

相关推荐

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

    db4o将Java对象直接持久化到磁盘,通过对象的引用关系来处理数据,简化了开发过程,特别是对于面向对象的设计模式来说,可以更好地保持数据的一致性和完整性。 ### 2. db4o的API介绍 db4o提供了一套直观的API来...

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

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

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

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

    db4o使用指南

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

    db4o开发指南和各种实例

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

    java数据库(db4o)

    在处理复杂的数据结构和对象关系时,db4o的灵活性和高性能尤其突出。 db4o虽然已经停止了官方的更新和支持,但其设计理念和实现方式仍然对现代NoSQL数据库有着深远的影响。对于学习和理解对象数据库以及如何在Java...

    DB4O Java开发应用

    DB4O会自动处理对象的序列化和反序列化。 - 从库中提取对象:通过`Database.query()`或`Database.ext().queryByExample()`方法,你可以根据对象的类型或实例查询数据库中的对象。 - 更新对象:如果你已经存储了一...

    db4o 权威指南

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

    db4o for java

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

    db4o中文指南

    这款数据库引擎已被验证具备优秀的性能,根据描述中的基准测试,db4o在与传统持久化方案的对比中排名第二,仅次于JDBC,且明显优于使用Hibernate/HSQLDB的方案,证明了面向对象并不一定意味着性能损失。 ### 1. db4...

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

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

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

    该资源为 db4o 之旅 系列文章: ...3.介绍面向对象数据库 db4o 的修改和删除,并对其中出现的问题进行细致分析,引入了“更新深度(update depth)”这一重要概念。 最后更新于2006 年 12 月 14 日 另外再推荐一个站点 ...

    db4o-8.0-java

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

    db4o6.4-java

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

    db4o8.0以及db4o中文指南

    db4o(Database for Objects)是一款开源的对象数据库系统,它允许开发者直接将Java或.NET对象存储到数据库中,无需进行ORM(对象关系映射)。db4o的目标是简化数据管理,提供更接近自然编程的方式,使开发过程更加...

    db4o-7.2-java

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

    DB4O_java

    DB4O(Database for Objects)是一款开源的对象数据库管理系统(Object-Relational Mapping,ORM),它专为Java平台设计,提供了一种将对象直接持久化的解决方案,免去了传统的对象关系映射的复杂性。DB4O的目标是...

    Db4o的简单操作项目

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

    db4o-5.0-tutorial-java帮助

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

    对象数据库db4o对象数据库db4o

    db4o(database for objects)是对象数据库的一种,它提供了对Java和.NET平台的完全支持,允许开发者以面向对象的方式来操作数据,极大地简化了数据管理和持久化的过程。 ### db4o概述 db4o的核心理念是“存储对象...

Global site tag (gtag.js) - Google Analytics