繁体   English   中英

那里有对象更改跟踪/版本控制 Java API 吗?

[英]Is there a object-change-tracking/versioning Java API out there?

我知道至少有两个字节码增强器在运行时修改“对象模型”以允许透明地执行事务。 其中一个是我每天在工作中使用的 Versant VOD 的一部分,另一个是 Terracotta 的一部分。 可能还有很多其他人,例如 ORM,但 Versant 在我的公司负责。

我的问题是,是否有这样一个开源 API 可以独立于其设计的产品而单独使用? 你可以说一个“可破解的”API。它应该只跟踪更改,而不是读取访问,这会显着降低代码速度。 换句话说,它不应该需要显式的读/写锁定。 这需要访问所有执行更改的类,而不仅仅是数据 model,或者需要在 memory 中保留某种形式的“先前版本”以进行比较。

我要解决的问题是我有“大”(32K 到 256K)object 个图,这些图在(NoSQL)数据库中“序列化”。 它们是长期存在的,必须定期重新序列化以获得更改的“历史记录”。 但它们的序列化成本相当高,而且大多数更改都很小。

我每次都可以完全序列化它们并在 stream 上运行二进制差异,但这听起来非常占用 CPU。 更好的解决方案是 API,它修改 model 上的写入操作以协议更改,以便在存储初始“图像”后,只需要存储协议。

我发现了一些关于 Apache Commons Beanutils 来比较对象的问题,但这对就地更改没有用; 我需要在每次“业务交易”之间对 model 进行完整克隆。

重申一下,我正在寻找一个“内存中”API,在同一个 JVM 中,它不涉及任何外部服务器应用程序。 涉及本机代码的 API 如果在 Win、Mac & Linux 上可用,则可以。API 目前不必单独打包 它只需要能够从“父项目”中提取它以形成一个独立的 API(父项目许可证必须允许这样做)。

我的 object 图将涉及许多大的 arrays,因此需要有效支持。

这些更改不仅用于审计,还可以重放或撤消。 更准确地说,使用反序列化的初始图和更改列表,我应该得到一个相同的最终图。 此外,从结束图开始,应该可以通过反向应用更改 go 回到初始图。 这使用完全相同的功能,但需要更改协议来保留旧值和新值。

API license 应该兼容商业使用。

[编辑] 到目前为止,我没有得到有用的答案,而且我想要的似乎并不存在。 这让我只有一个选择:实现它。 当我有一个有效的实施时,我会在这里发布一个链接作为答案,因为这是我项目的下一步,没有它我不能 go 转发。

[编辑] 我偶然发现了这个有点相关的问题: Is there a Java library that can "diff" two Objects?

Kryo v1 有一个序列化器,它知道最后一个被序列化的数据并且只发出一个增量。 读取时,它知道接收到的最后数据并应用增量。 增量是在字节级别完成的。 是序列化程序。 大部分工作都是由这个 class完成的。 这可以用于一些有用的方式,例如类似于 Quake 3 的网络。

这在 Kryo v2 中被省略了,因为 AFAIK 它从未被使用过。 此外,它没有进行广泛的测试。 它可以被移植并且可以做你需要的,或者作为你需要的基础。

上面还张贴在 JVM 序列化程序邮件列表中

在 object 级别执行它会有点棘手。 您可以编写类似于同时遍历两个object图的 FieldSerializer 的东西,但这将是独立代码,而不是 Kryo 序列化程序。 在每个级别,您都可以调用 equals。 写一个字节,这样当你读的时候你就知道它是否相等。 如果不是equals,用Kryo写object。对于同一个object,equals会被调用多次,尤其是嵌套较深的对象。

另一种方法是仅对标量和字符串执行上述操作,即仅由 Output class 写入的值。问题是遍历两个 object 图。 要使用 Kryo,我认为您必须复制所有序列化程序才能了解其他 object 图。

可能您可以将 Kryo 与您自己的 Output 一起使用,它在列表中收集值而不是写入它们。 使用它来“序列化”您的旧 object 图。 现在编写您自己的 Output 的另一个版本,它采用此列表并使用它来序列化您的新 object 图。 每次写入一个值时,首先检查列表中的下一个 object。 如果等于,写一个 1。如果不等于,写一个 0,然后是值。

这可以通过使用第一个 Output 两次来提高空间效率,一次在旧图上,一次在新图上。 现在您有两个值列表。 使用这些来编写一个位串,表示哪些是相等的。 这节省了为每个值写入一个完整字节的空间,但是有一个额外列表的开销。 最后,写出所有不相等的值。

要完成这个想法,您需要能够反序列化数据。 您将需要一个您自己的输入 class 版本,它从旧的 object 图中获取值列表。 您的 Input 首先读取位串(或每个值一个字节)。 对于相等的值,它返回列表中的值而不是从数据中读取。 如果值不相等,它会调用 super 方法从数据中读取。

我不确定这是否比在字节级别上做更快。 如果我不得不猜测,我会说它可能会更快。 将所有值存储在一个列表中将需要大量的装箱/拆箱,并且这种方法仍然分配所有字段,即使它们没有改变。 我怀疑无论哪种方式性能都会成为问题,所以我可能只是选择更简单的方法。 很难说那是哪一个...恢复增量内容或编写您自己的输出/输入类。

如果你想回馈 Kryo,那当然很棒。 :)

查看Content repository API for JavaArtifactory使用它来控制 maven 依赖项。 Apache Jackrabbit是此 JSR( JSR-283 版本 2 )的参考实现

我不知道这样的 API,但不会那么复杂:

更好的解决方案是 API,它修改 model 上的写入操作以协议更改,以便在存储初始“图像”后,只需要存储协议。

我会说你只需要 2 个组件:Action 和 ActionProcessor

您只需要保留已执行操作的列表(协议)。

interface ActionProcessor{
    void perform(Action action);
    void undoToDate(Date date);
} 

iterface Action{
    Date getDate();
    void perform();
    void undo();
}      

据我所知,GemFire 是一个 Gemstone(现在是 VmWare)企业产品,其功能类似于 Gemstone smalltalk OODB,但适用于 java。James Foster 制作了一系列关于 Gemstone 工作原理的视频 我发现它们很有趣。 Gemstone 有一个免费版本,可以用来构建小型(Seaside 网络)系统。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM