db4o などのオブジェクト データベースでのデータ メンテナンスの処理
-
19-09-2019 - |
質問
次のようなオブジェクト データベースを使用する際に、非常に混乱を招くと常に感じている点が 1 つあります。 db4o これは、通常 SQL/PL-SQL によって処理される複雑な移行を処理する方法です。
たとえば、リレーショナル データベースに my_users というテーブルがあるとします。もともと「full_name」という名前の列がありましたが、ソフトウェアが V2 になったので、この列を削除し、フルネームを空白スペースで分割し、最初の部分を「first_name」という名前の列に、2 番目の部分を 1 つの列に配置したいと考えています。 last_name という名前です。SQL では、単純に「first_name」列と「second_name」列を入力し、「full_name」という名前の元の列を削除します。
db4o などでこれを行うにはどうすればよいでしょうか?User.class のすべてのオブジェクトを検索し、first_name と last_name を設定しながら full_name を null に設定するスクリプトを作成する Java プログラムを作成する必要がありますか?次の svn commit を実行すると、full_name に対応するフィールド/Bean プロパティが存在しません。これは問題でしょうか?「スキーマ」が変更される運用アプリケーションで使用する場合は、バージョン x からバージョン x+1 にデータを移行するスクリプトを作成してから、バージョン x+2 で実際にしようとしているプロパティを削除したいと思うようです私のタイプの一部ではなくなったプロパティを変更する Java スクリプトを作成できないため、バージョン x+1 では削除してください。
問題の一部は、RDBMS が単純な大文字と小文字を区別しない文字列ベースの名前に基づいて参照しているオブジェクトを解決することであるようです。Java のような言語では型付けがこれよりも複雑で、ゲッターが使用されている場合はプロパティを参照できません。 /setter/field は実行時にロードされるクラスのメンバーではないため、基本的に同じスクリプト内に 2 つのバージョンのコードを含める必要があります (うーん、カスタム クラスローダーは面倒そうです)。新しいバージョンのクラスを格納する必要があります。別のパッケージ (面倒に聞こえます) を使用するか、前述したバージョン x+1 x+2 戦略を使用します (より多くの計画が必要です)。おそらく、私が db4o ドキュメントから収集したことのない明らかな解決策があるかもしれません。
何か案は?これがある程度の意味があることを願っています。
解決
まず、db4o は「単純な」処理を行います。 フィールドを自動的に追加または削除するようなシナリオ. 。フィールドを追加すると、既存のすべてのオブジェクトにデフォルト値が保存されます。フィールドを削除しても、既存のオブジェクトのデータはデータベース内に残り、引き続きアクセスできます。名前変更フィールドなどは 特別な「リファクタリング」呼び出し.
さて、あなたのシナリオでは次のようなことを行います:
- フィールド「full_name」を削除し、新しいフィールド「first_name」と「first_name」を追加します。
- すべての「Address」オブジェクトを反復処理します。
- 「StoredClass」API を介して古いフィールドにアクセスする
- 値の分割、変更、更新など。新しいフィールドに新しい値を設定し、オブジェクトを保存します。
「Address」クラスがあると仮定しましょう。「full_name」フィールドは削除されました。ここでは、それを「名」と「姓」にコピーする必要はありません。次に、次のようになります (Java)。
ObjectSet<Address> addresses = db.query(Address.class);
StoredField metaInfoOfField = db.ext().storedClass(Address.class).storedField("full_name", String.class);
for (Address address : addresses) {
String fullName = (String)metaInfoOfField.get(address);
String[] splitName = fullName.split(" ");
address.setFirstname(splitName[0]);
address.setSurname(splitName[1]);
db.store(address);
}
あなたが提案したように、バージョンバンプごとに移行コードを作成します。フィールドがクラスの一部ではなくなった場合は、上記のように 'StoredField'-API を使用してアクセスする必要があります。
すべての「保存された」クラスのリストを取得するには、次のようにします。 ObjectContainer.ext().storedClasses()
. 。と StoredClass.getStoredFields()
すべてのストアフィールドのリストを取得できます。もちろん、そのフィールドはクラスにもう存在しません。クラスが存在しない場合でも、「GenericObject」クラスを介してオブジェクトを取得し、それにアクセスできます。
アップデート:データベースを複数のバージョン手順で移行する必要がある複雑なシナリオの場合。
たとえば、バージョン v3 では、アドレス オブジェクトがまったく異なって見えます。そのため、v1 から v2 への「移行スクリプト」には、必要なフィールド (この例では名と確実な名前) がもうありません。これを処理するには複数の可能性があると思います。
- (このアイデアでは Java を想定しています。確かに、.NET にも同等のものがあります)。移行ステップを Groovy スクリプト. 。したがって、各スクリプトが他のスクリプトと干渉することはありません。次に、そこで移行に必要なクラスである「クラス」を定義します。したがって、各移行には独自の移行クラスがあります。と エイリアス groovy-migration-class を実際の Java クラスにバインドします。
- 複雑なシナリオ向けのリファクタリング クラスの作成。また、このクラスを次のようにバインドします エイリアス.
他のヒント
私は、ここに野生のショットのビットを取っています。
あなたは奇妙な比較を作っている:あなたは「ホット移行」にデシベルを望んでいた場合は、おそらくあなたが説明x+1
、x+2
のバージョン管理のアプローチを行う必要があるだろうが、私は本当に知らない - 私は「wouldnトン私は、DBの専門家ではないので、どちらかのSQLでこれを行う方法を知っています。
、しかし、あなただけの店で各オブジェクトの古いオブジェクトを削除し、新しいオブジェクトを格納し、古いデータから新しいオブジェクトをインスタンス化することにより、ワンステップでそれを行うことができます。 のdb4oを参照してください。参照するます。
しかし正直:あなたが実際に操作を実行するために制約チェック(そしておそらくトリガなど)、アクティベート解除する必要がありますので、RDBMSの同じプロセスは、あまりにも複雑である - あなたが提供した例ではおそらくないが、最も現実世界の例のために。すべての後に、文字列の分割が少しゲインがあることをとても簡単です。
SQLでは私は単純に "FIRST_NAME" を埋めるだろうと "second_name" 列
はい、のシンプルなの文字列の分割操作では、は単にのことを行うことができます。しかし、一般的なリファクタリングのシナリオでは、あなたが簡単にSQLで表現されていない可能性があり、ルールの大規模かつ複雑なセットに基づいて再構造化オブジェクトだ、複雑な計算、または外部データソースが必要になる場合があります。
これを行うには、あなたも、コードを記述する必要があると思います。
すべての後、私は2つのプロセスではあまり違いが表示されません。あなたはいつも、ライブデータと注意する必要があります、そして、あなたは確かに両方のケースでバックアップを行います。リファクタリングは楽しいですが、持続性はトリッキーであるので、それを同期すると、どのような場合での挑戦です。