2009-08-21 41 views
4

我有一个简单的Java类,我需要序列化以作为值存储在RDBMS或键值存储中。该类只是简单类型(本机类型或本地类型的地图/列表)属性的集合。问题是这个类可能会随着时间的推移而发展(可能是:添加新属性,不太可能,但仍然可能:重命名属性,更改属性的类型,删除属性)。Java中的版本化序列化

我希望能够优雅地处理类版本中的更改。特别是,当试图从旧版本反序列化实例时,我希望能够指定某种处理程序来管理旧实例向最新版本的转换。

我不认为Java的内置序列化在这里是合适的。在我尝试推出自己的解决方案之前,我想知道是否有人知道可能有帮助的现有库?我知道很多Java的替代序列化方法,但我特别寻找能够让我随着时间的推移修改类定义的东西。

编辑:

对于它的价值,我结束了协议缓冲区(http://code.google.com/p/protobuf/)序列化去,因为它的灵活添加和重命名字段,而正对一块少的代码,我要保持(参考使用readObject/writeObject的自定义Java序列化)。

回答

4

Java序列化允许串行形式的定制提供readObjectwriteObject方法。连同ObjectInputStream.readFields,ObjectOutputStrean.putFields和定义serialPersistentFields,序列化的形式可以与实现类中的实际字段无关。

然而,Java序列化产生不透明的数据是不适合阅读和通过其他技术写作。

+0

我没有意识到readFields和putFields方法,所以非常感谢。 – 2009-08-23 21:22:28

0

我有类似的问题。当你有多个版本的对象时,我发现Java的serialVersionUID没有什么帮助。所以我推出了自己的。

这是我做的,以拯救我们的用户会话,

  1. 在我的数据库,除了对序列化对象BLOB字段,我添加了一个版本列。
  2. 无论何时我们改变会话对象,我都会保存旧的类,例如SessionV3。
  3. 会话总是以当前版本号写入数据库。
  4. 阅读会话时,如果版本是最新的,它会直接反序列化到会话对象中。否则,将其反序列化为旧对象并手动复制到当前会话对象(SessionV3 => Session)中。
  5. 有一段时间,我们运行一个数据库脚本来删除真正的旧会话版本,因此我们可以从代码中清除旧会话。如果我们关心旧会话,我们也可以选择将它们转换。

有可能做到这一点更简单的方法,但我们的方法为我们提供了最大的灵活性。

0

从来没有尝试过,但你可以做一些与自定义启动加载程序在运行时被反序列化对象加载类文件的正确版本。

2

也许你应该将你的Java类映射到关系模型中。将某些语言序列化的blob转储到数据库列是一种可怕的方法。

+0

我不想使用标准对象关系映射出于几个原因: 1)我的序列化类具有许多属性,它们是值列表和地图值。虽然可以用SQL来表示这些数据,但它会增加数据库模式的复杂性,特别是在适当地处理对类模式的更改时。 2)我想保持足够的灵活性,以切换到键值存储模型,其中的值只是我的序列化类。 – 2009-08-23 21:27:25

1

这是非常简单的使用读写对象。

尝试将serialversionuid设置为固定值,然后为您的版本定义静态最终字段。 readobject然后可以使用switch语句根据版本构造字段。我们使用它来在我们的文件系统上存储历史数据。它的检索速度非常快 - 以至于用户无法区分这些差异。