c++对象数据库

C++ Object Database

本文关键字:数据库 对象 c++      更新时间:2023-10-16

我正在写我的学士论文。它的目标是用c++编写对象数据库(类似于CoreData)。要求之一是支持反射关系(1-1,1- m,M-M)和动态对象加载。

我目前的设计包括简单的DDL语言与代码生成。用户编写他想要持久化的类,然后编写这些类之间的关系。像这样:

Person {
    string name;
    int salary;
}
relation Person.boss(1) references Person inverse Person.subs(M);

从这里,我生成带有类定义的c++头文件,带有方法定义的c++源代码。类的所有原语字段都是公共的,关系是私有的,只能通过get/set或get/add/remove/clear方法访问。在这些方法中,我保持了自反关系的一致性。例如:在方法setBoss中,我将执行以下操作:

void setBoss(ptr<Person> val) {
        if (boss) {
            boss->subs.remove(this);
        }
        boss = val;
        boss->subs.add(this);
        boss.modified = true
    }

这段代码全部生成,并且可以工作。但是我的主管要求我在没有任何形式的代码生成的情况下这样做,并尽可能地遵循CoreData。我认为他的想法是在c++中模拟动态对象,其中每个对象可以存储在数据库中包含map<string,value>,并从这个映射中读取字段。我认为这种设计对于c++来说显然是错误的,因为像这样存储一切将要求每个字段都是自定义类,对每个字段访问都有引用和动态强制转换,我甚至没有谈论存储其他类,它们使用自定义共享指针(这是一个模板,因此动态强制转换将不起作用)。

还有一个元数据的问题,我如何在这个系统中定义模式?我可能可以使用访问器,它访问所有字段,并使用一些宏技巧检索它们的名称和类型,但是自反关系呢?我不知道。

在我的方法中,我可以以某种方式版本添加字段并为它们生成迁移代码。(将模式版本存储在持久数据库中,然后,当我打开该数据库时,检查版本并运行生成的迁移代码)。

我在这里错过了什么吗?我的方法完全错了吗?

[当然,以下是一个观点,但要怪问题,不是我]

我在这里错过了什么吗?我的方法完全错了吗?

完全错了-不。但并非没有风险。

您的方法(类似orm的方法)的缺点之一是:每次更改结构时,"数据存储迁移"将是一场噩梦。否则,您将不得不把处理模式的不同版本的噩梦强加给用户(程序员同事)。

看看Google的protobuff,了解一下正在进化的生成结构的问题——它们不处理存储,只处理数据传输。然而,你必须小心地导航(哪些成员是必需的/可选的)并遵守一些严格的规则(例如,在协议的两个版本之间,只添加but 决不删除字段)。

还有一个元数据的问题,我如何在这个系统中定义模式?

这不是一个很好的论文题目吗?当然,这不是微不足道的,但为什么要微不足道呢?

如果没有代码生成,您必须在编译级方法(使用DSL)或以运行时为中心的方法(使用虚拟函数、动态强制转换和typeid/typeindex的混合)之间进行选择。

DSL练习是我们今年碰巧经历的事情,具有讽刺意味的是,它与您的问题非常密切相关:1- 1,1 - n, N-N集合。当然,对于学士论文来说,这可能有点夸张,但它可能是这样的:https://github.com/C5T/Current/blob/1b9716438d323b8b47eb8d5bf5907e98ee3be1dc/Storage/test.cc#L92-L120

在你的情况下,我将开始直接询问主管是否他们正在寻找编译时或运行时的解决方案。在时间和loc方面,运行时可能更容易实现,但它提供的保证要少得多,结果也不太实用。不过,仅对于字符串<=>字符串映射,两个集合和虚拟引用的策略类就可以很好地完成这项工作。