ルーム:すべての人のための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クエリを記述する必要がありません。








All Articles