当有人谈到给物体补水时,这是什么意思?

我在网上看到一个名为Hydrate的Java项目,它在不同的表示形式(RDMS到OOPS到XML)之间转换数据。这就是物体水化的一般意义吗?在表示之间转换数据?这是否意味着从存储的表示中重构对象层次结构?


相对于更通用的术语水合物

使对象水合就是获取内存中存在的对象,该对象还不包含任何域数据(“真实”数据),然后用域数据(例如来自数据库、网络或文件系统)填充它。

来自Erick Robertson对这个答案的评论:

反序列化==实例化+水化

如果您不需要担心起泡的性能,并且不需要调试数据访问API内部的性能优化,那么您可能不需要显式地处理水合。您通常会使用反序列化,这样可以编写更少的代码。一些数据访问api不提供此选项,在这些情况下,您还必须自己显式地调用水合步骤。

关于Hydration概念的更多细节,请参阅Erick Robertson对同一问题的回答。

关于Java项目的水合物

你特别提到了这个框架,所以我研究了一下。

据我所知,我不认为这个项目使用了“水合物”这个词在非常一般的意义上。我认为它在标题中的使用是“序列化”的近似同义词。如上所述,这种用法并不完全准确:

参见:http://en.wikipedia.org/wiki/Serialization

将数据结构或对象状态转换为可存储的格式[…]],然后在同一或另一个计算机环境中重新构建。

我不能直接在水合物常见问题中找到他们名字背后的原因,但我得到了他们意图的线索。我想他们之所以选择“水合物”这个名字,是因为这个库的目的与流行的Hibernate框架类似,但它的设计思路完全相反。

大多数orm(包括Hibernate)采用内存中面向对象模型的方法,其次考虑数据库。水合物库采用了一种面向数据库模式的方法,保留了关系数据结构,并让你的程序更清晰地在它们之上工作。

打个比方来说,这个库的名字仍然是:水合物就像“准备使用的东西”(就像重新为干燥的食品补水)。它是Hibernate的反义词,它更像是“为冬天准备一些东西”(就像动物冬眠)。

就我所知,将图书馆命名为“水合物”的决定与通用计算机编程术语“水合物”无关。

当使用通用的计算机编程术语“水合物”时,性能优化通常是动机(或调试现有的优化)。即使库支持对对象何时以及如何填充数据的粒度控制,时间和性能似乎也不是该名称或库功能的主要动机。该库似乎更关心支持端到端映射和模式保存。

虽然正如梅林提到的那样,它有点多余,但在我的经验中,它只指填充/填充对象,而不是实例化/创建对象,所以当你需要精确时,它是一个有用的词。

水化是指用数据填充对象的过程。一个尚未水化的对象已经实例化,并表示一个确实有数据的实体,但数据尚未加载到该对象中。这样做是出于性能考虑。

此外,在讨论从数据库或其他数据源加载数据的计划时,还使用术语hydration。下面是一些例子:

当您只加载了一些字段到对象中,而不是所有字段时,您可以说对象是部分水合的。之所以可以这样做,是因为这些其他字段对于当前操作不是必需的。因此,没有理由浪费带宽和CPU周期来加载、传输和设置这些不需要使用的数据。

此外,还有一些ORM,如Doctrine,在实例化对象时不水合对象,而仅在该对象中访问数据时水合对象。这是一种有助于不加载不打算使用的数据的方法。

这是一个相当老的问题,但似乎对以下术语的含义仍然存在混淆。希望这能消除歧义。

水合物

当你看到这样的描述,“一个物体正在等待数据,正在等待水化”,这是令人困惑和误导的。对象不会等待对象,水合作用只是用数据填充对象的行为。

以JavaScript为例:

const obj = {}; // empty object
const data = { foo: true, bar: true, baz: true };

// Hydrate "obj" with "data" 
Object.assign(obj, data); 
console.log(obj.foo); // true
console.log(obj.bar); // true
console.log(obj.baz); // true

任何为obj增加价值的东西都是“水合”它。在这个例子中,我只是使用Object.assign()。

由于“序列化”和“反序列化”这两个术语在其他回答中也提到过,这里有一些例子来帮助消除这些概念与水合作用的歧义:

序列化

console.log(JSON.stringify({ foo: true, bar: true, baz: true }));

反序列化

console.log(JSON.parse('{"foo":true,"bar":true,"baz":true}'));

在PHP中,你可以从它的名字w/o调用构造函数创建一个新类,就像这样:

require "A.php";
$className = "A";
$class = new \ReflectionClass($className);
$instance = $class->newInstanceWithoutConstructor();

然后,您可以调用setter(或公共属性)