CanastaとSenoritを使用してAndroid用のOrmを作成する、パート3

エントリー


私のAndroidアプリケーションの開発を中断した後、1月の終わりに、より美しく、より便利にする方法について、より多くの新しいアイデアが頭に浮かんできました。 リフレクション中に、アプリケーションを作成する方法が少し変わったため、わずか3週間前にオブジェクトモデルに到達しました。 そしてほとんどすぐに、 UCAOrmを完成させる必要に直面しました 。 すでに導入されている革新だけでなく、まだ開発プロセスにのみあるものについても学びたい人は誰ですか?

変更と追加


私が最初に出会ったのは、 ContentProviderCursorの必要性でした。
ContentProviderには特に問題はありませんでした -抽象OrmContentProviderはContentProviderを継承し、これまでにOrmWhereを受け入れてOrmCursorを返すqueryと、 更新されたインスタンスを受け入れるupdateの 2つのメソッドを実装します。 OrmCursorAbstractCursorから継承され、必要なすべてのメソッドを実装することに加えてオブジェクトのリストを返すgetEntitiesメソッドも実装します。 実装の観点から最も興味深いのは、列名の配列を返すgetColumnNames関数( getOrmFields関数既にやり直されています)と、指定された列の値を返すプライベートgetObject関数です。 これらのクラスにより、同期アカウントの開発が大幅に簡素化されました。
2番目の革新は、新しいフィールドタイプのサポートです: booleanおよびint arraybooleanですべてが多かれ少なかれ明確な場合、 配列についてもう少し詳しく説明します。 最初に、「 class_name field_name 」という名前と、配列のコンポーネントのタイプの単一の列を持つ追加のテーブルを作成するというアイデアが思いつきました。 しかし、推論してみると、 OrmEntityから継承したクラスを持つ配列はアーキテクチャ全体を破壊し、開発者は他の非プリミティブ型を手動でシリアル化する必要があるという結論に達しました。 ここから、 ormは文字列に完全にシリアル化され、完全に逆シリアル化されるプリミティブ型の配列のみをサポートすることにしました。 おそらく、問題はdoubleで発生する可能性があり、その形式には文字列の形式で配列の要素の区切りであるコンマを含めることができますが、 英語のロケールをハード設定することで簡単に解決できます。
また、ついにOrmHelperの相続人のgetDefaultValuesメソッドの実装に到達しました 。 これは次のようになります。
@Override public void getDefaultValues(Class<? extends OrmEntity> entityClass, List<OrmEntity> valueList) { } 

したがって、 2番目の部分からお気に入りのモデルのデフォルト値を追加するには、次のように実装します。
  public void getDefaultValues(Class<? extends OrmEntity> entityClass, List<OrmEntity> valueList) { if (entityClass.equals(CarType.class)) { valueList.add(new CarType("Passenger")); valueList.add(new CarType("Truck")); } } 

さて、これで最初の記事で説明したhardexの最もおいしい問題-データスキーマの更新に到達しました。

データスキーマの更新


繰り返しますが、モデルに戻って、 Carの本質を考えてみましょう。
  @Table(rightJoinTo = {Truck.class}) public class Car extends BaseEntity { @Column(name = "car_type") private CarType type; @Column private List<Wheel> wheels; @Column(name = "engine_power") private int enginePower; @Column(name = "doors_count") private int doorsCount; } 

別のフィールドを追加するとします。
  @Column(name = "max_speed") private int maxSpeed; 

この場合、マニフェストのデータベースのバージョンを変更する必要があります。
 <meta-data android:name="UO_DB_VERSION" android:value="2" /> 

そして、 onUpdateヘルパーメソッドにコードを記述します。
  @Override protected void onUpgrade(int oldVersion, int newVersion) { if (newVersion == 2) { OrmUtils.UpdateTable(Car.class).work(); } } 

他に作業方法が必要なのはなぜですか? 」-誰かが尋ねます。 そして、データスキームを変更するための可能なオプションを見てみましょう:
  1. 新しいフィールドがスキーマに追加されます。
  2. スキーマからフィールドが削除されます。
  3. フィールドの名前が変更されます。
  4. フィールドのタイプは変化しています。

ほとんどの場合、多くの人はすでに、問題を引き起こさない唯一のポイントが最初であると推測していますが、それらを順番に検討します。

フィールドの追加

ここではすべてが簡単です。ormはテーブルからフィールドを取得し、クラスのフィールドと比較します。 新しいフィールドがオブジェクトモデルにあるとき、それはひきつります
 ALTER TABLEADD COLUMN 
デフォルト値が必要な場合は、アノテーションで指定する必要があります。

フィールド削除

アルゴリズムの最初は前のものと似ています:フィールドを比較し、削除する必要があるフィールドを見つけます。 それで、ほとんど、よくある質問で示されているように。 私が理解できない唯一のことは、2番目のコピーが必要な理由です。なぜなら、テーブルのゼロをドロップした後、一時的なものの名前を変更するだけで永続的なものになるからです!

フィールド名を変更

そして、ここでの仕事はあなたのアシスタントではありません! Ormは、単にフィールドの名前を変更したことを理解せず、2つのことを行います。データベースから古い名前のフィールドを削除し、新しいフィールドを新しいフィールドに追加します。 もちろん、これはold_nameフィールドを追加することでアノテーションでも破られる可能性がありますが、これはすでに多すぎるように思われ、 ormは彼に何をすべきかを正確に伝えることでオフロードできます。 前述の観点から、この段落では、 名前変更メソッドが必要です。
 OrmUtils.UpdateTable(Car.class).renameColumn("old_column_name", "new_column_name"); 

フィールドではなく、列の名前を指定する必要があることに注意してください! その結果、 ormは変更する必要があるものを理解するためにクラス全体およびデータベース内のすべてのフィールドをウール化せず、1つの列の名前を単に変更します。
また、列の追加を支援することもできます。
 OrmUtils.UpdateTable(Car.class).addColumn("column_name"); 

列を削除します。
 OrmUtils.UpdateTable(Car.class).deleteColumn(“column_name”); 

SQLクエリの形式で名前を変更すると、いくつかの疑問が生じました。 まず、目的のフィールド名で新しいテーブルを作成し、古いテーブルのデータをコピーし、単純に削除して新しいテーブルの名前を変更することで、削除のようにこれを決定しました。 しかし、その後、私はこの記事に出会い、この方法を試してみる予定です。

フィールドタイプを変更する

オームは、再び、あなたのためにすべてを行うことができますが、あなたは彼を助けることができます:
 OrmUtils.UpdateTable(Car.class).changeColumnType("column_name"); 

原則として、2番目のパラメーターは新しいタイプの列を渡すことができますが、プログラマーに間違ったタイプを指定してから、sold orm (:-))する機会を与えたくありませんでした。 古いタイプのデータと新しいタイプのデータの非互換性の問題は、データベース自体によって解決され、古いテーブルを新しいテーブルにコピーするときに例外をスローします。 ただし、2番目のパラメーターとしてtrueを渡すことで、列を簡単にリセットすることもできます。
 OrmUtils.UpdateTable(Car.class).changeColumnType(“column_name”, true); 

また、デザインには、型の非互換性がある場合にのみフィールドをクリアする必要があるが、まだ実行されていないことを示すパラメーターがありました。

おわりに


これらは、過去2週間にUCAOrm受けた変更です 。 少し上に書いたように、 Updaterの作業まだ進行中であり、すべてがまだテストされていないため、すべてがgithubにアップロードされているわけでありません。 また、テーブルの初期作成を少し単純化するというアイデアもあります。OrmUtilsでcreateByPackegメソッドを呼び出しormがマークされたクラスを検索するパッケージの名前を渡すだけです。 しかし、これは単なるアイデアです。
いつものように、新しいアイデアや提案があれば嬉しいです。 すぐにアップデートをお楽しみに。

Source: https://habr.com/ru/post/J216419/


All Articles