ルーム:すべての人のためのAndroid上のデータストレージ

ルームは、 Google I / Oで今年導入されたAndroidアプリケーションにアプリケーションデータを保存する新しい方法です これは、関連するアプリケーションアーキテクチャをサポートするGoogleのライブラリグループである、新しいAndroidアーキテクチャの一部です。 ルームは、レルム、ORMLite、GreenDaoなどの代替として提供されます。


Roomは、Androidに組み込まれている低レベルのSQLiteバインディング用の高レベルインターフェイスです。詳細については、 ドキュメントをご覧ください。 コンパイル時にほとんどの作業を行い、組み込みのSQLite APIの上にAPIを作成するため、 CursorまたはContentResolverを使用する必要はありません。


部屋を使用して


まず、プロジェクトに部屋を追加します。 その後、データがどのように見えるかをRoomに転送する必要があります。 次のような単純なモデルクラスがあるとします。


public class Person { String name; int age; String favoriteColor; } 

ルームPersonクラスを伝えるには、 Entityアノテーションをクラスに追加し、 @ PrimaryKeyをキーに追加します。


 @Entity public class Person { @PrimaryKey String name; int age; String favoriteColor; } 

これら2つの注釈により、 RoomPersonのインスタンスを保持するテーブルを作成する方法を認識します。


モデルを設定する際に考慮すべき重要なこと:データベースに保存される各フィールドは、パブリックであるか、標準のJava Beansスタイルのgetterおよびsetter(たとえば、 getName()およびsetName(string name) )である必要があります。


Personクラスには、 Roomがテーブルを作成するために必要なすべての情報が含まれていますが、データベースからデータを実際に追加、クエリ、または削除する方法はありません。 これが、データアクセスオブジェクト(DAO)を作成する必要がある理由です。 DAOは、データベース自体にインターフェイスを提供し、Personに保存されたデータの操作に関与します。


Personクラスの簡単なDAOインターフェイスを次に示します。


 @Dao public interface PersonDao { //  Person   @Insert void insertAll(Person... people); //  Person   @Delete void delete(Person person); //   Person   @Query("SELECT * FROM person") List<Person> getAllPeople(); //   Person     @Query("SELECT * FROM person WHERE favoriteColor LIKE :color") List<Person> getAllPeopleWithFavoriteColor(String color); } 

最初に気づくのは、 PersonDaoクラスではなくインターフェイスであることです。 もう1つの興味深い詳細は、 Query ()アノテーションのSQLステートメントです。 SQLステートメントは、データベースから取得する情報をRoomに伝えます。 また、コンパイル時にチェックされます。 したがって、ListメソッドgetAllPeopleWithFavoriteColor( 色名 )のシグネチャをLi​​st getAllPeopleWithFavoriteColor( int color )に変更すると、Roomはコンパイル時にエラーをスローします。

 incompatible types: int cannot be converted to String 

また、SQL式でタイプミスをした場合、たとえば、 favouriteColor( singular )の代わりにfavoriteColors( 複数 )を書くと、Roomもコンパイルエラーをスローします。


 There is a problem with the query: [SQLITE_ERROR] SQL error or missing database (no such column: favoriteColors) 

インターフェイスであるため、PersonDaoのインスタンスを取得することはできません。 DAOクラスを使用できるようにするには、データベースクラスを作成する必要があります。 舞台裏では、このクラスはデータベース自体を維持し、DAOインスタンスを提供します。


データベースクラスは数行で作成できます。


 @Database(entities = {Person.class /*, AnotherEntityType.class, AThirdEntityType.class */}, version = 1) public abstract class AppDatabase extends RoomDatabase { public abstract PersonDao getPersonDao(); } 

これはデータベース構造の単なる説明ですが、データベース自体は単一のファイルに存在します。 populus-databaseというファイルに保存されているAppDatabaseのインスタンスを取得するには、次のように記述する必要があります。


 AppDatabase db = Room.databaseBuilder(getApplicationContext(), AppDatabase.class, "populus-database").build(); 

データベース内にあるすべてのPersonに関するすべてのデータを取得する場合、次のように記述できます。


 List<Person> everyone = db.getPersonDao().getAllPeople(); 

ルームを使用する利点


ほとんどのORMとは異なり、 Roomは注釈プロセッサを使用して、データストレージ全体を実行します。 これは、RealmやSugarORMを含む他の多くのORMとは異なり、アプリケーションクラスもモデルクラスもRoomで何も拡張しないことを意味します。 上記のQuery ()アノテーションのエラーで見たように、コンパイル時にSQLクエリの正確性をチェックするオプションもあります。これにより、多くの手間を省くことができます。


ルームでは、データの変更を観察して、それらを建築コンポーネントのLiveData APIとRxJava 2の両方と統合することもできます。つまり、データベースの変更をアプリケーションの複数の場所に表示する必要がある複雑なスキームがある場合、ルームは通知を行います変更について。 この強力なアドオンは、1行に含めることができます。 必要なのは、戻り値の型を変更することだけです。


たとえば、次のメソッド:


 @Query("SELECT * FROM person") List<Person> getAllPeople(); 

次のようになります。


 @Query("SELECT * FROM person") LiveData<List<Person>> /* or Observable<List<Person>> */ getAllPeople(); 

部屋の最大の制限:関係


ルームの最大の制限は、他のORMなど、他の種類のエンティティとの関係を自動的に処理しないことです。 これは、ペットを追跡する場合:


 @Entity public class Person { @PrimaryKey String name; int age; String favoriteColor; List<Pet> pets; } @Entity public class Pet { @PrimaryKey String name; String breed; } 

そのルームは、PersonとPetの関係を維持する方法を知らないため、コンパイルエラーをスローします。


 Cannot figure out how to save this field into database. You can consider adding a type converter for it. 

コンパイルエラーは、オブジェクトをSQLに直接格納できるプリミティブに変換する型コンバーターを提供します。 Listはプリミティブに縮小できないため、別の操作を行う必要があります。 これは、1人の人が多くのペットを持つことができる1対多の関係です。 ルームはそのような関係をモデル化することはできませんが、逆の関係を処理できます。各ペットには1人の人物がいます。 これをシミュレートするには、 Pet in Personのフィールドを削除し、 ownerIdフィールドをPetクラスに追加します。


 @Entity public class Person { @PrimaryKey String name; int age; String favoriteColor; } @Entity(foreignKeys = @ForeignKey( entity = Person.class, parentColumns = "name", childColumns = "ownerId")) public class Pet { @PrimaryKey String name; String breed; String ownerId; // this ID points to a Person } 

これにより、Roomはオブジェクト間の外部キーを制限します。 ルームは1対多および多対1の関係をトリガーしませんが、その関係を表現するツールを提供します。


特定の人物に属するすべてのペットを取得するには、特定の所有者IDを持つすべてのペットを検索するクエリを使用できます。 たとえば、次のメソッドをDAOに追加できます。


 @Query("SELECT * FROM pet WHERE ownderId IS :ownerId") List<Pet> getPetsForOwner(String ownerId); 

ルームを使用する必要がありますか?


アプリケーションにデータを保存するようにすでに設定しており、それで満足する場合は、何も変更しないでください。 各ORMおよび埋め込みSQLite実装は、以前と同様に機能し続けます。 部屋は、データを保存するための別の方法です。


SQLiteを使用する場合、または使用する場合は、Roomを試してください。 高度なクエリを実行するために必要なすべての機能を備えており、データベースを単独でサポートするためにSQLクエリを記述する必要がありません。



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


All Articles