0

いくつかのデータ オブジェクトをシリアル化し、データベースに格納していました。長い間、データベースにはそのようなオブジェクトが何百もありました。最近、これらのクラスの 1 つの構造を変更する必要がありました。これらのオブジェクトを逆シリアル化すると、エラーがスローされます。

カスタムのシリアライゼーションとデシリアライゼーションはまだ書いていません。の使用も、シリアル化中defaultSerialVersionUIDのデフォルトであったため、ここでは役に立ちません。1L

基になるクラス構造が変更された後、それらを逆シリアル化するより良い方法はありますか?

4

3 に答える 3

3

いくつかのデータ オブジェクトをシリアル化し、それらをデータベースに格納していました...

それは/大きな間違いでした、IMO。データ オブジェクトに対応するテーブルを作成して維持する必要はありませんでしたが、Java オブジェクトのシリアル化はこの種の目的のために設計されておらず、この種の脆弱性は欠点の 1 つです。


@EJP と @sidoh の回答は、古いバージョンのクラスを手に入れることができれば、現在の穴から抜け出すためのいくつかのアイデアを提供します。いくつかのアプローチがあります。

  • 互換性を壊す変更前のコード/スキーマの状態にロールバックし、ミスを回避する方法で作業をやり直します。

  • ロールバックしないで、現在読み取り可能なオブジェクトを読み取り可能な形式にロードし、保存されているバージョンを更新するアドホック コンバーターを作成します。

前者は実用的ではないかもしれません。たとえば、他の変更が多すぎる場合、またはコード/データが本番環境にある場合。

後者には、バージョン管理からクラスの古いバージョンと新しいバージョンを取得し、古いクラスをロードし、新しいクラスのインスタンスに変換して保存するアドホック コンバーターを構築する必要があります。これの難しさは、同じ JVM で同じクラスの 2 つの異なるバージョンを同時に使用できる Java アプリケーションを構築することです。

  • クラスパスの異なるバージョンで 2 つのクラスローダーをインスタンス化できます。しかし問題は、JVM が 2 つのクラスのセットを異なるタイプとして扱い、両方のバージョンに対する静的バインディングを不可能にすることです。リフレクションを介してこれに対処することもできますが、特にそれぞれのオブジェクト API が広範囲に及ぶ場合は、非常に面倒になります。

  • これは、2 段階のプロセスとして実行できます。ステージ 1 は、古いクラスを使用してロードし、ファイルに書き込む (たとえば) JSON を使用してクラスをシリアル化することです。ステージ 2 では、JSON を読み取り、それを使用して新しいクラスを使用してオブジェクトを作成し、オブジェクトのシリアル化を使用してそれらをシリアル化します。


3 つ目の方法は、シリアル化されたオブジェクトを微調整するアドホック コンバーターを作成することです。基本的に、古いシリアル化されたフォームと新しいシリアル化されたフォームの違いを理解してから、低レベル API を使用してシリアル化されたオブジェクトを読み書きすることで、シリアル化されたオブジェクトを書き換える必要があります。これのバリエーションは、古い形式と新しい形式の両方を理解する新しいバージョンのクラスにカスタムの readObject とメソッドを実装することです。ただし、古いオブジェクトにカスタム バージョン フィールドがない場合、これは注意が必要です。この種のものはシリアライゼーション仕様の範囲を超えていることに注意してください...


しかし、IMO の最良の代替手段は、Java シリアライゼーションの使用をやめる機会としてこれを使用することです。古いクラスを使用してオブジェクトを読み取り、JSON または XML BLOB として、または ORM マッピングを使用して、データベースに通常の SQL テーブルに書き戻します。

于 2013-04-06T01:47:48.600 に答える
1

これらの変更を行う前に最初に読んでおくべきことは、Object Serialization Specification の Object Versioning の章です。既存のシリアライゼーションとの互換性を維持しながら、できることとできないことを正確にレイアウトします。ほとんどの人が考えているよりもはるかに多くのことを許可しますが、たとえば、継承チェーンの変更は許可されません。これは、あなたが行ったように聞こえます。

2 番目に行う必要があるのは、準拠していない変更を元に戻すことです。

于 2013-04-06T00:30:17.200 に答える