ルームは、 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つの注釈により、 RoomはPersonのインスタンスを保持するテーブルを作成する方法を認識します。
モデルを設定する際に考慮すべき重要なこと:データベースに保存される各フィールドは、パブリックであるか、標準の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( 色名 )のシグネチャをList 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クエリを記述する必要がありません。